How to pass an array of pointer by JNA? - jna

Java:
Pointer[] myArray;
myArrayis an array of Pointers.
C++
myfun(void** myArray){
void *a = myArray[0];
}
How to pass an array of pointer by JNA?
I've tried myfun(Pointer[] myArray) in Java but it reported not support argument type in runtime like below:
Caused by: java.lang.IllegalArgumentException: class [Lcom.sun.jna.Pointer; is not a supported argument type (in method myfun in class com.xx.yy.zz)

thanks , I've solved this problem
create a structure
in Java:
public class xxPointer extends Structure {
public Pointer myPointer;
in C++:
struct xxPointer {
void* myPointer;
};
interface:
in Java:
myFun(xxPointer.ByReference br);
in C++:
myFun(xxPointer * xp)
in Java:
xxPointer.ByReference rp = new xxPointer.ByReference();
xxPointer.ByReference pointers = (xxPointer[]) rRecord.toArray(array count);
assignment value for pointers[i].myPointer
myFun(rp);

Related

Getting an error on a qsort compare function

I'm using C++Builder 10.4.2 and having a problem with qsort. I rarely use qsort so I might be making a clumsy mistake. Array 'buffer' is a 2D 'char' array with more than 26,000 rows of single words.
This is the call:
qsort((void *)buffer,wordcount,sizeof(buffer[1]),sort_function);
This is the compare function:
int TForm::sort_function(const void *a, const void *b)
{
return( strcmp((char *)a,(char *)b) );
}
This is the error message. Notice that it's complaining about sort_function for 4th argument:
search.h(46): candidate function not viable: no known conversion from 'int (__closure *)(const void *, const void *)' to 'int (*)(const void *, const void *) __attribute__((cdecl))'
What is 'int (__closure *)'? Is there a way to fix my compare function?
__closure is a Borland compiler extension for obtaining a pointer to a non-static class method, without regard to the type of class being used. This is most commonly used in VCL/FMX components, which allow you to assign event handlers from any class you want, which is not something that standard C++ typically allows you to do.
qsort() expects a C-style function pointer in the 4th parameter. You can't get such a pointer to a non-static class method.
To solve this, you need to use either:
a standalone function
a static class method
a non-capturing C++ lambda (C++11 or higher only)
Since your sort_function() does not need access to your TForm object, declaring sort_function() as static would be the simplest fix:
// .h
class TForm
{
...
private:
static int sort_function(const void *a, const void *b);
void doSomething();
...
};
// .cpp
int TForm::sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
However, it really should be a standalone function instead since it really has no relation to your TForm class at all:
// .cpp
static int sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}

FatalExecutionEngineError on accessing a pointer set with memcpy_s

See update 1 below for my guess as to why the error is happening
I'm trying to develop an application with some C#/WPF and C++. I am having a problem on the C++ side on a part of the code that involves optimizing an object using GNU Scientific Library (GSL) optimization functions. I will avoid including any of the C#/WPF/GSL code in order to keep this question more generic and because the problem is within my C++ code.
For the minimal, complete and verifiable example below, here is what I have. I have a class Foo. And a class Optimizer. An object of class Optimizer is a member of class Foo, so that objects of Foo can optimize themselves when it is required.
The way GSL optimization functions take in external parameters is through a void pointer. I first define a struct Params to hold all the required parameters. Then I define an object of Params and convert it into a void pointer. A copy of this data is made with memcpy_s and a member void pointer optimParamsPtr of Optimizer class points to it so it can access the parameters when the optimizer is called to run later in time. When optimParamsPtr is accessed by CostFn(), I get the following error.
Managed Debugging Assistant 'FatalExecutionEngineError' : 'The runtime
has encountered a fatal error. The address of the error was at
0x6f25e01e, on thread 0x431c. The error code is 0xc0000005. This error
may be a bug in the CLR or in the unsafe or non-verifiable portions of
user code. Common sources of this bug include user marshaling errors
for COM-interop or PInvoke, which may corrupt the stack.'
Just to ensure the validity of the void pointer I made, I call CostFn() at line 81 with the void * pointer passed as an argument to InitOptimizer() and everything works. But in line 85 when the same CostFn() is called with the optimParamsPtr pointing to data copied by memcpy_s, I get the error. So I am guessing something is going wrong with the memcpy_s step. Anyone have any ideas as to what?
#include "pch.h"
#include <iostream>
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace std;
// An optimizer for various kinds of objects
class Optimizer // GSL requires this to be an unmanaged class
{
public:
double InitOptimizer(int ptrID, void *optimParams, size_t optimParamsSize);
void FreeOptimizer();
void * optimParamsPtr;
private:
double cost = 0;
};
ref class Foo // A class whose objects can be optimized
{
private:
int a; // An internal variable that can be changed to optimize the object
Optimizer *fooOptimizer; // Optimizer for a Foo object
public:
Foo(int val) // Constructor
{
a = val;
fooOptimizer = new Optimizer;
}
~Foo()
{
if (fooOptimizer != NULL)
{
delete fooOptimizer;
}
}
void SetA(int val) // Mutator
{
a = val;
}
int GetA() // Accessor
{
return a;
}
double Optimize(int ptrID); // Optimize object
// ptrID is a variable just to change behavior of Optimize() and show what works and what doesn't
};
ref struct Params // Parameters required by the cost function
{
int cost_scaling;
Foo ^ FooObj;
};
double CostFn(void *params) // GSL requires cost function to be of this type and cannot be a member of a class
{
// Cast void * to Params type
GCHandle h = GCHandle::FromIntPtr(IntPtr(params));
Params ^ paramsArg = safe_cast<Params^>(h.Target);
h.Free(); // Deallocate
// Return the cost
int val = paramsArg->FooObj->GetA();
return (double)(paramsArg->cost_scaling * val);
}
double Optimizer::InitOptimizer(int ptrID, void *optimParamsArg, size_t optimParamsSizeArg)
{
optimParamsPtr = ::operator new(optimParamsSizeArg);
memcpy_s(optimParamsPtr, optimParamsSizeArg, optimParamsArg, optimParamsSizeArg);
double ret_val;
// Here is where the GSL stuff would be. But I replace that with a call to CostFn to show the error
if (ptrID == 1)
{
ret_val = CostFn(optimParamsArg); // Works
}
else
{
ret_val = CostFn(optimParamsPtr); // Doesn't work
}
return ret_val;
}
// Release memory used by unmanaged variables in Optimizer
void Optimizer::FreeOptimizer()
{
if (optimParamsPtr != NULL)
{
delete optimParamsPtr;
}
}
double Foo::Optimize(int ptrID)
{
// Create and initialize params object
Params^ paramsArg = gcnew Params;
paramsArg->cost_scaling = 11;
paramsArg->FooObj = this;
// Convert Params type object to void *
void * paramsArgVPtr = GCHandle::ToIntPtr(GCHandle::Alloc(paramsArg)).ToPointer();
size_t paramsArgSize = sizeof(paramsArg); // size of memory block in bytes pointed to by void pointer
double result = 0;
// Initialize optimizer
result = fooOptimizer->InitOptimizer(ptrID, paramsArgVPtr, paramsArgSize);
// Here is where the loop that does the optimization will be. Removed from this example for simplicity.
return result;
}
int main()
{
Foo Foo1(2);
std::cout << Foo1.Optimize(1) << endl; // Use orig void * arg in line 81 and it works
std::cout << Foo1.Optimize(2) << endl; // Use memcpy_s-ed new void * public member of Optimizer in line 85 and it doesn't work
}
Just to reiterate I need to copy the params to a member in the optimizer because the optimizer will run all through the lifetime of the Foo object. So it needs to exist as long as the Optimizer object exist and not just in the scope of Foo::Optimize()
/clr support need to be selected in project properties for the code to compile. Running on an x64 solution platform.
Update 1: While trying to debug this, I got suspicious of the way I get the size of paramsArg at line 109. Looks like I am getting the size of paramsArg as size of int cost_scaling plus size of the memory storing the address to FooObj instead of the size of memory storing FooObj itself. I realized this after stumbling across this answer to another post. I confirmed this by checking the value of paramsArg after adding some new dummy double members to Foo class. As expected the value of paramsArg doesn't change. I suppose this explains why I get the error. A solution would be to write code to correctly calculate the size of a Foo class object and set that to paramsArg instead of using sizeof. But that is turning out to be too complicated and probably another question in itself. For example, how to get size of a ref class object? Anyways hopefully someone will find this helpful.

Streams backport compile error

Using streamsupport with a Java 7 javac compiler I encounter the following compile error:
[ERROR] method map in interface java8.util.stream.Stream<T>
cannot be applied to given types; [ERROR] required:
java8.util.function.Function<? super java.lang.Object,? extends
R>
[ERROR] found: <anonymous
java8.util.function.Function<java.lang.Integer,java.lang.String>> [ERROR] reason: no instance(s) of type variable(s) R exist so that
argument type <anonymous
java8.util.function.Function<java.lang.Integer,java.lang.String>> conforms to formal parameter type java8.util.function.Function<?
super java.lang.Object,? extends R>
My code is
List<Object> listSum = RefStreams.iterate(0, new UnaryOperator<Integer>() {
#Override
public Integer apply(Integer n) {
return n+1;
}
}).limit(10000).map(new Function<Integer,String>() {
#Override
public String apply(Integer n) {
return String.format("%04d", n);
}
}).collect(Collectors.toList());
I want to know what to do and why this error occurred? Thanks
You'll have to be prepared that type inference in Java 6 / 7 compilers is not up to par with Java 8 / Java 9 compilers.
So, sometimes a statement / expression that compiles with 8 can't be compiled unchanged with 6 or 7. Providing a type witness usually helps the compiler figure out the correct types in Java 6 / 7.
I would do it this way (this works for me with javac from Oracle JDK 1.7.0_80):
List<String> list = RefStreams.<Integer, Integer>iterate(0, new UnaryOperator<Integer>() {
#Override
public Integer apply(Integer n) {
return n + 1;
}
}).limit(10000).map(new Function<Integer, String>() {
#Override
public String apply(Integer n) {
return String.format("%04d", n);
}
}).collect(Collectors.<String>toList());
Note the two type witnesses here:
RefStreams.<Integer, Integer>iterate and Collectors.<String>toList.
The first is there to help the compiler infer the correct type for the map call and the second is there so that the result is correctly inferred as List<String> instead of List<Object>.

Dart. Child class and constructor initializer list

I play with Dart (leaf through Tour of the Dart Language) and I found that I can't use initializer list on child classes. Why?
main() {
var rbt = new Robot.fromJson({'x':21, 'y':21});
}
class Human {
}
class Robot extends Human {
int x;
int y;
Robot.fromJSON(Map map) : x = map['x'], y = map['y'] {
print('Robot location is $x, $y');
}
}
Causes an error:
Exception: No constructor 'Robot.fromJson' declared in class 'Robot'.
NoSuchMethodError: method not found: 'Robot.fromJson'
Receiver: Type: class 'Robot'
Arguments: [Instance of '_LinkedHashMap']
Dart is case-sensitive
fromJSON vs fromJson

boost python overload operator ()

I would like to bind the operator() using Boost::Python but I don't really see how to do this. Consider the example:
C++:
class Queuer
{
public:
void Queuer::operator()(const qfc::Queue & iq, const qfc::Message & im) const;
void Queuer::operator()(const qfc::Agent & ia, const qfc::Message & im) const;
// some other overloaded operator() methods
};
So in a Python script, after importing the module I'm using (called qfc), I would like to do:
Python:
>>> queuer = qfc.Queuer()
// instantiating a Message an Agent and a Queue object
>>> queuer(queue,message)
>>> queuer(agent,message)
>>> ...
Would you have any idea on how to do it? maybe with boost::python call<>?
Thank you,
Kevin
When exposing the Queuer class, define a __call__ method for each Queuer::operator() member function. Boost.Python will handle the appropriate dispatching based on types. The only complexity is introduced with pointer-to-member-function syntax, as the caller is required to disambiguate &Queuer::operator().
Additionally, when attempting to pass derived classes in Python to a C++ function with a parameter of the Base class, then some additional information needs to be exposed to Boost.Python:
The base C++ class needs to be exposed with class_. For example, class_<BaseType>("Base").
The derived class needs to explicitly list its base classes when being exposed with bases_. For example, class_<DerivedType, bases<BaseType> >("Derived"). With this information, Boost.Python can do proper casting while dispatching.
Here is a complete example:
#include <iostream>
#include <boost/python.hpp>
// Mockup classes.
struct AgentBase {};
struct MessageBase {};
struct QueueBase {};
struct SpamBase {};
struct Agent: AgentBase {};
struct Message: MessageBase {};
struct Queue: QueueBase {};
struct Spam: SpamBase {};
// Class with overloaded operator().
class Queuer
{
public:
void operator()(const AgentBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Agent." << std::endl;
}
void operator()(const QueueBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Queue." << std::endl;
}
void operator()(const SpamBase&, const MessageBase&) const
{
std::cout << "Queuer::operator() with Spam." << std::endl;
}
};
/// Depending on the overlaod signatures, helper types may make the
/// code slightly more readable by reducing pointer-to-member-function syntax.
template <typename A1>
struct queuer_overload
{
typedef void (Queuer::*type)(const A1&, const MessageBase&) const;
static type get(type fn) { return fn; }
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose only the base class types. Do not allow the classes to be
// directly initialized in Python.
python::class_<AgentBase >("AgentBase", python::no_init);
python::class_<MessageBase>("MessageBase", python::no_init);
python::class_<QueueBase >("QueueBase", python::no_init);
python::class_<SpamBase >("SpamBase", python::no_init);
// Expose the user types. These classes inerit from their respective
// base classes.
python::class_<Agent, python::bases<AgentBase> >("Agent");
python::class_<Message, python::bases<MessageBase> >("Message");
python::class_<Queue, python::bases<QueueBase> >("Queue");
python::class_<Spam, python::bases<SpamBase> >("Spam");
// Disambiguate via a varaible.
queuer_overload<AgentBase>::type queuer_op_agent = &Queuer::operator();
python::class_<Queuer>("Queuer")
// Disambiguate via a variable.
.def("__call__", queuer_op_agent)
// Disambiguate via a helper type.
.def("__call__", queuer_overload<QueueBase>::get(&Queuer::operator()))
// Disambiguate via explicit cast.
.def("__call__",
static_cast<void (Queuer::*)(const SpamBase&,
const MessageBase&) const>(
&Queuer::operator()))
;
}
And its usage:
>>> import example
>>> queuer = example.Queuer()
>>> queuer(example.Agent(), example.Message())
Queuer::operator() with Agent.
>>> queuer(example.Queue(), example.Message())
Queuer::operator() with Queue.
>>> queuer(example.Spam(), example.Message())
Queuer::operator() with Spam.
Thanks for your help.
Actually I've already tested the static cast solution. In reality, I need to pass a qfc::lqs::Message or qfc::lqs::Agent or qfc::lqs::Spam when invoking queuer(). qfc::lqs::Message for example, as for qfc::lqs::Agent inherit from qfc::Message and qfc::Agent respectively.
So can I "cast" qfc::lqs::Message, qfc::lqs::Agent and qfc::lqs::Spam to qfc::Message, qfc::Agent and qfc::Spam when invoking the operator() so that the signature corresponds to operator() ?
This to avoid the error shown below:
error: invalid static_cast from type '<unresolved overloaded function type>' to type 'void (qfc::lqs::Queuer::*)(const qfc::lqs::Queue&, const qfc::lqs::Message&)const'

Resources