I have the following C++ method compiled using Visual Studio 2017:
extern "C" __declspec( dllexport )
Info* __stdcall GetInfo(InfoProvider* infoProvider)
{
static_assert(std::is_pod<Info>::value, "Must be Plain Old Data in order to be safely copied between DLL boundaries");
Info info = new Info();
Info->data1 = infoProvider->data1;
Info->data2 = infoProvider->data2;
return info;
}
In Java code, it is mapped by Java Native Runtime using interface method with following signature:
Info GetInfo(Pointer infoProvider);
final class Info extends Struct {
public final Signed32 data1;
public final Signed32 data2;
public R2VInfo(final Runtime runtime) {
super(runtime);
data1 = new Signed32();
data2 = new Signed32();
}
}
It works.
The above C++ method causes memory leak, so I would like to change it to return result by value:
extern "C" __declspec( dllexport )
Info __stdcall GetInfo(InfoProvider* infoProvider)
{
static_assert(std::is_pod<Info>::value, "Must be Plain Old Data in order to be safely copied between DLL boundaries");
Info info{};
Info.data1 = infoProvider->data1;
Info.data2 = infoProvider->data2;
return info;
}
I use the same Java JNR mapping:
Info GetInfo(Pointer infoProvider);
But it does not work - Access Violation. Native method is invoked, but with some dandling pointer value.
How to return by value in JNR?
To return a value from a function, you must include a return statement, followed by the value to be returned, before the function's end statement. If you do not include a return statement or if you do not specify a value after the keyword return, the value returned by the function is unpredictable.
JavaScript provides for passing one value back to the code that called it after everything in the function that needs to run has finished running. JavaScript passes a value from a function back to the code that called it by using the return statement . The value to be returned is specified in the return keyword.
The Python return statement is a special statement that you can use inside a function or method to send the function's result back to the caller. A return statement consists of the return keyword followed by an optional return value. The return value of a Python function can be any Python object.
We can return more than one value from a function by using the method called “call by address”, or “call by reference”. In the invoker function, we will use two variables to store the results, and the function will take pointer-type data. So we have to pass the address of the data.
JNI build around old pure K&R C to be compatible with all available compilers. Returning a structure from a function was introduced in C89 and was fully implemented significantly later with C++ standard together. Today it is still possible to find such old C compiler in many java-friendly environments like small devices or sim-cards. So I don't think that JNI would be upgraded to C89 or even C99.
For your case, I would recommend to write an additional C-code that handles calling of a library function. The code could be implemented in two ways:
Info* __stdcall GetInfo(InfoProvider* infoProvider)
you should write free-function like:extern "C" __declspec( dllexport )
void __stdcall FreeInfo(Info* info)
{
static_assert(std::is_pod<Info>::value, "Must be Plain Old Data in order to be safely copied between DLL boundaries");
delete info;
}
Info __stdcall GetInfo(InfoProvider* infoProvider)
you should write a wrapper:extern "C" __declspec( dllexport )
void __stdcall GetInfo(InfoProvider* infoProvider, Info* info)
{
static_assert(std::is_pod<Info>::value, "Must be Plain Old Data in order to be safely copied between DLL boundaries");
Info infoProvider = GetInfo(infoProvider);
info->data1 = infoProvider.data1;
info->data2 = infoProvider.data2;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With