JNI C++ Callbacks - java-native-interface

I have a c++ function which accepts a lambda as a parameter. This function calls a piece of java code.
I was wondering how would I get the java code to call the lambda once it's done, in effect calling back to the C++ code.

JavaCPP does that. For example, the following code in C++:
#include "jniFoo.h"
int main() {
JavaCPP_init(0, NULL);
foo(6, 7);
}
With this Java class:
import com.googlecode.javacpp.*;
import com.googlecode.javacpp.annotation.*;
public class Foo {
public static class Callback extends FunctionPointer {
public #Name("foo") void call(int a, int b) {
System.out.println("bar " + a * b);
}
}
}
Produces the following output:
bar 42

Java does not know C++ or lambdas. You should prepare a general C callback that will know which lambda to execute.

Related

How to hold a List<> of opaque handles in CLI/C++?

I am writing a CLI/C++ wrapper for a C-library in order to use it in C#. It must be said, I only have access to the C header file and the .lib of the C-library, not the source code.
Some of the functions I am trying to wrap are returning opaque handles, such as:
typedef struct SanEvent_s *SanEvent;
typedef struct SanValue_s *SanValue;
Returning objects of this type on the C# end seems like trouble to me, as I don't know the implementation of the struct (I tried returning the SanEvent type in the C++ wrapper but on the C# end that type is not accessible due to "protection level" or whatever it said). My plan at the moment is therefore to write some helper functions, which instead just return an integer which represents an, for example, San Event in a list or something. The list would be kept in the managed C++ wrapper, where I can actually manage the San Event type.
My problem is, I don't really know how to do this with this type of type.
This:
using System::Collections::Generic::List;
namespace Wrapper {
public ref class Analytics
{
private:
static List<SanEvent^>^ events = gcnew List<SanEvent^>();
}
}
Gives me the errors: handle to handle, pointer, or reference is not allowed
The right hand side also complains about expected type specifier + the same error as above.
Can anyone give me some tips on how I could tackle this issue neatly and efficiently? My List implementation is not carved in stone, and I am open to better suggestions.
Let's imagine following SanEvent declaration
struct SanEvent_s
{
int test;
};
typedef SanEvent_s *SanEvent;
And following C++ API to work with such event:
SanEvent GetEvent()
{
auto e = new SanEvent_s();
e->test=42;
return e;
}
int UseEvent(SanEvent pEvent)
{
return pEvent->test;
}
All this code contained in static library project (fully native, no CLR).
Then we have C++/CLI project to wrap this static lib.
Here we have wrapper for event itself:
#include "./../CppLib/SanEvent_s.h"
public ref class SanEventWrapper: Microsoft::Win32::SafeHandles::SafeHandleZeroOrMinusOneIsInvalid
{
public:
static SanEventWrapper^ GetWrapper()
{
return gcnew SanEventWrapper(GetEvent());
}
internal:
SanEventWrapper(SanEvent event):SafeHandleZeroOrMinusOneIsInvalid(true)
{
this->e = event;
this->handle = System::IntPtr(event);
}
int UseWrapper()
{
return ::UseEvent(this->e);
}
protected:
bool ReleaseHandle() override
{
//todo: release wrapped event
return true;
}
private:
SanEvent e;
};
And another class which uses such a wrapper
public ref class SanEventConsumer
{
public:
int ConsumeEvent(SanEventWrapper^ wrapper)
{
return wrapper->UseWrapper();
}
};
And finally, how to use all this from C#:
var wrapper = SanEventWrapper.GetWrapper();
var consumer = new SanEventConsumer();
var res = consumer.ConsumeEvent(wrapper);
Console.WriteLine(res);
This should print 42;
Notes:
Notes:
this is a very simplified sample. It should be adapted ytrin accordance with semantics of 'SanEvent' struct as well as with respect of requirements of SafeHandle documentation (https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle?view=netframework-4.8 and https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.safehandles.safehandlezeroorminusoneisinvalid?view=netframework-4.8)
you should decide if your wrapper will own the SunEvent object or not and implement ReleaseHandle and Dispose accordingly to this.
you may consider to use another base class from this list https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.safehandles?view=netframework-4.8 instead of 'SafeHandleZeroOrMinusOneIsInvalid' or even make direct inhernitance from SafeHandle.
you can even think about dropping SafeHandle-related stuff at all and making the simple wrapper by your own, but it can give some surprises in connection with GC.
depending of the semantics of the SunEvent you may be also need to implement factory to guarantee that you always return to the managed code the same instance of wrapper for all equals values of raw native pointer.
Here's something similar to what #Serg has above, but explicitly goes with the idea that you have NO IDEA in the C# world what's inside the object.
So if you have a C++/CLI library made in VS, you get this in the .h file:
#pragma once
#include <cstdint>
using namespace System;
namespace CppCliLibrary {
public ref class Class1
{
public:
static IntPtr getOpaqueInstance(int32_t argument);
static void useOpaqueInstance(IntPtr obj);
static void freeOpaqueInstance(IntPtr obj);
};
}
Like above, using IntPtr to represent a pointer to "whatever". The corresponding .cpp file is this:
#include "pch.h"
#include "CppCliLibrary.h"
#include <string>
#include <iostream>
namespace CppCliLibrary
{
class OpaqueCppClass
{
public:
OpaqueCppClass(int32_t arg)
: m_int(arg) { }
int32_t m_int;
};
}
IntPtr CppCliLibrary::Class1::getOpaqueInstance(int32_t argument)
{
return IntPtr(new OpaqueCppClass(argument));
}
void CppCliLibrary::Class1::useOpaqueInstance(IntPtr obj)
{
CppCliLibrary::OpaqueCppClass* deref = reinterpret_cast<CppCliLibrary::OpaqueCppClass *>(obj.ToPointer());
std::cout << "Contents of class are: " << deref->m_int << std::endl;
}
void CppCliLibrary::Class1::freeOpaqueInstance(IntPtr obj)
{
CppCliLibrary::OpaqueCppClass* deref = reinterpret_cast<CppCliLibrary::OpaqueCppClass*>(obj.ToPointer());
std::cout << "Deleting class with contents: " << deref->m_int << std::endl;
delete deref;
}
Then in the C# file you have this:
namespace CsCoreConsole
{
class Program
{
static void Main(string[] args)
{
// Get an instance
var instance = CppCliLibrary.Class1.getOpaqueInstance(52);
// Use it
Console.WriteLine("Got an instance we're using");
CppCliLibrary.Class1.useOpaqueInstance(instance);
Console.WriteLine("Freeing it");
CppCliLibrary.Class1.freeOpaqueInstance(instance);
// Add a bunch to a list
List<IntPtr> opaqueInstances = new List<IntPtr>();
for(int i = 0; i < 5; i++)
{
opaqueInstances.Add(CppCliLibrary.Class1.getOpaqueInstance(i * 10));
}
// Use them all
foreach(var cur in opaqueInstances)
{
CppCliLibrary.Class1.useOpaqueInstance(cur);
}
// Delete them all
foreach (var cur in opaqueInstances)
{
CppCliLibrary.Class1.freeOpaqueInstance(cur);
}
}
}
}
Of course the C# project needs to reference the C++/CLI one, but you get the idea here. The C++/CLI is a factory (nothing more, nothing less) for IntPtr and it can use it as well, because to C# it's opaque. C# knows of nothing more than IntPtr.
The idea from Serg is to wrap it more, in a type-safe way. Sure, that can work, but this is the "even more raw" variant, if you want to put it "directly" into a List<>

Call a managed class member function from an unmanaged class member [duplicate]

How do I pass a function pointer from managed C++ (C++/CLI) to an unmanaged method? I read a few articles, like this one from MSDN, but it describes two different assemblies, while I want only one.
Here is my code:
1) Header (MyInterop.ManagedCppLib.h):
#pragma once
using namespace System;
namespace MyInterop { namespace ManagedCppLib {
public ref class MyManagedClass
{
public:
void DoSomething();
};
}}
2) CPP Code (MyInterop.ManagedCppLib.cpp)
#include "stdafx.h"
#include "MyInterop.ManagedCppLib.h"
#pragma unmanaged
void UnmanagedMethod(int a, int b, void (*sum)(const int))
{
int result = a + b;
sum(result);
}
#pragma managed
void MyInterop::ManagedCppLib::MyManagedClass::DoSomething()
{
System::Console::WriteLine("hello from managed C++");
UnmanagedMethod(3, 7, /* ANY IDEA??? */);
}
I tried creating my managed delegate and then I tried to use Marshal::GetFunctionPointerForDelegate method, but I couldn't compile.
Yes, you want Marshal::GetFunctionPointerForDelegate(). Your code snippet is missing the managed function you'd want to call, I just made one up. You will also have to declare the managed delegate type and create an instance of it before you can get a function pointer. This worked well:
#include "stdafx.h"
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed(push, off)
typedef void (* UnmanagedSummer)(int arg);
void UnmanagedMethod(int a, int b, UnmanagedSummer sum)
{
int result = a + b;
sum(result);
}
#pragma managed(pop)
ref class Test {
delegate void ManagedSummer(int arg);
public:
static void Run() {
Test^ t = gcnew Test();
ManagedSummer^ managed = gcnew ManagedSummer(t, &Sum);
IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(managed);
UnmanagedSummer functionPointer = static_cast<UnmanagedSummer>(stubPointer.ToPointer());
UnmanagedMethod(1, 2, functionPointer);
GC::KeepAlive(managed); // Important: ensure stub can't be collected while native code is running
System::Diagnostics::Debug::Assert(t->summed == 3);
}
void Sum(int arg) {
summed += arg;
}
int summed;
};
int main(array<System::String ^> ^args)
{
Test::Run();
return 0;
}
Here's another way to do it based on my experiences implementing a .NET wrapper in C++/CLI around the CartoType C++ map rendering library. This is tested and working code.
The C++ API has an asynchronous Find function which takes a callback:
TResult CartoType::CFramework::FindAsync(FindAsyncCallBack aCallBack,const TFindParam& aFindParam,bool aOverride = false);
The callback is a function of this type:
using FindAsyncCallBack = std::function<void(std::unique_ptr<CMapObjectArray> aMapObjectArray)>;
The task is to provide a .NET wrapper for this function by adding C++/CLI code to the existing wrapper system. First I define a suitable delegate type for my .NET function (an equivalent to FindAsyncCallback in the C++ API):
public delegate void FindAsyncDelegate(MapObjectList^ aMapObjectList);
The signature of the .NET function is thus:
Result FindAsync(FindAsyncDelegate^ aDelegate,FindParam^ aFindParam,bool aOverride);
The main implementation problem to be solved is how to call the native C++ function and provide a native callback function which can then call the delegate passed in by the caller of the .NET function. An associated task is to keep the delegate and the native callback function object alive until the asynchronous function's thread has done its job. Here's how it's done.
I define a C++/CLI delegate type that's the same as the C++ callback function type, and a class to hold the delegate passed in by the caller to the .NET function (of type FindAsyncDelegate), and a delegate of the type to be passed to C++ (of type NativeAsyncHandler):
delegate void NativeAsyncHandler(std::unique_ptr<CMapObjectArray> aMapObjectArray);
ref class FindAsyncHelper
{
public:
FindAsyncHelper(Framework^ aFramework,FindAsyncDelegate^ aDelegate):
m_framework(aFramework),
m_delegate(aDelegate)
{
}
void Handler(std::unique_ptr<CMapObjectArray> aMapObjectArray)
{
MapObjectList^ o = gcnew MapObjectList;
SetMapObjectList(m_framework,o,*aMapObjectArray);
m_delegate(o);
// Remove this object from the list held by the framework so that it can be deleted.
m_framework->m_find_async_helper_list->Remove(this);
}
Framework^ m_framework;
FindAsyncDelegate^ m_delegate;
NativeAsyncHandler^ m_native_handler;
};
The idea is that we create a FindAsyncHelper object with the two delegates in it, then call the native FindAsync function with the native delegate, arranged to call Handler(), which then calls the original caller's delegate.
And here is how it's implemented:
typedef void(*FIND_ASYNC_CALLBACK)(std::unique_ptr<CMapObjectArray> aMapObjectArray);
Result Framework::FindAsync(FindAsyncDelegate^ aDelegate,FindParam^ aFindParam,bool aOverride)
{
if (aDelegate == nullptr || aFindParam == nullptr)
return Result::ErrorInvalidArgument;
TFindParam param;
SetFindParam(param,aFindParam);
FindAsyncHelper^ h = gcnew FindAsyncHelper(this,aDelegate);
h->m_native_handler = gcnew NativeAsyncHandler(h,&FindAsyncHelper::Handler);
IntPtr p = Marshal::GetFunctionPointerForDelegate(h->m_native_handler);
FIND_ASYNC_CALLBACK f = static_cast<FIND_ASYNC_CALLBACK>(p.ToPointer());
TResult error = m_framework->FindAsync(f,param,aOverride);
// Keep h alive by adding it to a list.
m_find_async_helper_list->Add(h);
return (Result)(int)error;
}
Some notes:
The statements
FindAsyncHelper^ h = gcnew FindAsyncHelper(this,aDelegate);
h->m_native_handler = gcnew NativeAsyncHandler(h,&FindAsyncHelper::Handler);
create a FindAsyncHandler object and store a native handler object in it; keeping it here means we only have one object to keep alive, the FindAsyncHandler. The next statements:
IntPtr p = Marshal::GetFunctionPointerForDelegate(h->m_native_handler);
FIND_ASYNC_CALLBACK f = static_cast<FIND_ASYNC_CALLBACK>(p.ToPointer());
get a function pointer that can be passed to native code, and cast it to the right function pointer type. We can't cast it directly to the std::function type used in FindAsyncCallback, so the cumbersome extra typedef is necessary.
At last the native FindAsync function can be called:
TResult error = m_framework->FindAsync(f,param,aOverride);
And then, to make sure the various callback functions stay alive, the FindAsyncHandler is added to a list owned by the main framework object:
m_find_async_helper_list->Add(h);
It is taken off the list when the task is completed and FindAsyncHelper::Handler is called.

Registering a c++ callback method in a C code

I have a c++ class and c code as well. Following is rough (logically the same) and minimalised code
// C++ class - Car.cpp
void Car :: initialise()
{
WheelT mWheel; // WheelT is a struct in Wheel.c
mWheel.run(wheelGotFlat); // <---- I want to pass here the c++ callback method , so that if the wheel goes flat , the callback should hit
}
static void car :: wheelGotFlat() // <--- callback method
{
}
// C code - Wheel.c
void checkStatus(callback aCb)
{
// if wheel is flat
// ----- here I want to hit the callback method that was passed as argument to run()
}
void run(callback aCb)
{
checkStatus(aCb);
}
How to do this ??
To make a C++ function callable from C, use extern "C" void foo(int) { ... }, for example. To make it call a member function, you'll have to make the callback a stub written in C++, but callable from C, that then calls the member function.
Note that using a static member function will often work, but is actually undefined behavior. See this for more details.

Combining function, bind, c++ and managed code

I have a c++ function which is expecting a function object (AuthenticateNotifyFunc) to be passed to it thus:
class lc_Authenticate
{
public:
typedef enum {
kAbort,
kContinue
} lc_AuthenticateStatus;
typedef std::tr1::function<lc_AuthenticateStatus (const string &msg)> AuthenticateNotifyFunc;
bool Authenticate(lc_AuthenticateParams &params,
AuthenticateNotifyFunc notifyFunc);
}
Within a managed c++ project, I am attempting to define a parameter to pass to the above function thus:
public ref class Form1 : public System::Windows::Forms::Form
{
public:
lc_Authenticate::lc_AuthenticateStatus UpdateStatus(const string &msg)
{
<<DO SOMETHING>>
return(lc_Authenticate::kContinue);
}
void test()
{
string appKey, appSecret;
appKey = GetString(this->appKeyTextBox->Text);
appSecret = GetString(this->appSecretTextBox->Text);
lc_Authenticate dbauth;
lc_AuthenticateParams params(appKey, appSecret);
// DOESN'T COMPILE won't let me take address of member function
// or know about _1
lc_Authenticate::AuthenticateNotifyFunc func =
std::tr1::bind(&Form1::UpdateStatus, this, _1);
dbauth.Authenticate(params, func);
}
};
So I am trying to implement a generic method of passing a function to a c++ method in such a way that it doesn't care whether the passed function is static or a member function. And I'm not clear how do do this from managed code.
You cannot bind to an instance method of a managed class by design. The garbage collector moves the object around when compacting the heap, causing this to change. You'll need to use a managed delegate. So you can't avoid a native helper class that provides the stable callback you need for your function<>. You can get back to managed code from there with Marshal::GetFunctionPointerForDelegate().

Python to C++: From Deriv, to Base, to Deriv again

I'm using Boost.Python to expose my C++ code to Python. I've encountered a difficulty related to having an object passed from one language to the other multiple times. Here's what I want to do:
The C++ code
class Base
{
public:
void baseTest() {
std::cout << "Base::basetest()";
}
};
class Deriv
: public Base
{
public:
void derivTest() {
std::cout << "Deriv::derivTest()";
}
};
void call(Base& b, boost::python::object func)
{
func(b);
}
BOOST_PYTHON_MODULE(event)
{
using namespace boost;
using namespace boost::python;
class_<Base>("Base")
.def("baseTest", &Base::baseTest)
;
class_<Deriv, bases<Base>>("Deriv")
.def("derivTest", &Deriv::derivTest)
;
def("call", call);
}
Python code
from event import *
def callback(deriv):
deriv.baseTest() # works fine
deriv.derivTest() # crash!
def run():
d = Deriv()
call(d, callback)
What I want to happen
C++: Calls the run() function defined in Python. (No problem here)
Python: run() creates a new Deriv object; it passes it and a function object, callback, back to C++, through the call function. (Also okay)
C++: call() takes the Deriv object as a Base&. It passes the Base-reference to the Python callback it received through the second parameter.
Python: The callback receives the Base object from C++. However, it expects it to be a Deriv: if I call derivTest() the program crashes. However, if I call baseTest(), it doesn't crash.
How can I make the callback not crash?
Thanks for the comments, I found the solution to this. It's actually quite simple, you just have to wrap the Base object in a shared_ptr instead of passing it by reference, like this:
void call(boost::shared_ptr<Base> b, boost::python::object func)
{
func(b);
}
But be careful about something. I tried to used std::shared_ptr that comes with Visual C++ 2010 Express (the 'memory' header) and it caused a crash. I had to use the boost::shared_ptr for it to work. (I'm using version 1.46.1 of Boost.)