We have the following callback in C which I need to bind it using pybind11 so that, it can be called from python.
typedef gpointer (*CopyFunc) (gpointer data, gpointer user_data);
then We have a structure that uses the above-defined callback as follows
struct _DATA{
int element_size;
int num_empty_elements;
CopyFunc copy_func;
}DATA;
Currently, we have binded them using the following approach. First we register the callback as follows
std::function<gpointer(gpointer,gpointer)> g_copyfunc;
static void register_copyfunc(std::function<gpointer(gpointer,gpointer)> const& func)
{
g_copyfunc = func;
}
then we call this register callback as follows
static gpointer copyfunc_wrapper(gpointer arg1, gpointer arg2)
{
return g_copyfunc(arg1, arg2);
}
from python we pass the callback function using bindings to register the function as follows
m.def("register_copyfunc",
[](std::function<COPYFUNC_SIG> const& func) {
register_copyfunc(func);
});
then we set the function to the structure element as follows
m.def("set_user_copyfunc",
[](DATA *data, std::function<COPYFUNC_SIG> const& func) {
data->copy_func = (CopyFunc) copyfunc_wrapper;
});
Is there any approach within pybind11 to bind this callback without following the above hack?
Related
I'm trying to invoke a member function by pthread by using an external wrapper but it doesn't quite work for me, I get a seg fault. Why is this?
Here's a little test program that displays the problem:
#include <iostream>
#include <pthread.h>
class test {
public:
test();
~test();
void RunTh(void);
private:
pthread_t *pid;
};
void *Run_wrp(void *context);
void test::RunTh(void)
{
while(1);
}
test::test()
{
pthread_create(pid,NULL,&Run_wrp,this);
}
test::~test(){}
int main(void) {
test tmp;
std::cin.get();
}
void *Run_wrp(void *context)
{
((test*)context)->RunTh();
}
Your pid member variable is just a pointer, not an actual pthread_t object.
Change it to:
private:
pthread_t pid;
Then create the new thread with:
pthread_create(&pid,NULL,&Run_wrp,this);
Also, if you want to keep everything contained in the class, you can make your Run_wrp() function a static member function of test, as long as you keep the same signature (return value/arguments). It needs to be static, as non-static functions take the this pointer to the class as a hidden argument, and thus end up with a different signature than what you need for pthread_create().
I am new to programming. I was not able to understand the use of call back by function pointer clearly. Please help me to understand where actually the function pointers are needed. I have given two examples. One callback using function pointer and other the normal way(Function calling a function). Forgive me if it appears silly.
#include<stdio.h>
void A()
{
printf("Hello");
}
void B(void(*ptr)())
{
ptr();
}
int main
{
void (*p)() = A;
B(p);
}
Another method
#include<stdio.h>
void A()
{
printf("Hello");
}
void B()
{
A();
}
int main
{
B();
}
What is the use of callback using function pointer when this can be achieved in a simpler way?
I have a project where I am expanding existing native C++ compatible code functionality for a customer-facing library by integrating a driver from a managed DLL, which seems like the opposite direction for most marshaling questions. Since there can be multiple devices using this one driver, each device needs to be its own object, with its own callback methods. This integration will take the form of a native wrapper DLL that exposes the native class interface to the customer-facing library, which will pass an instance of a member method callback function pointer to the DLL. I need to pass a native method member instance (non-static) as a delegate to the managed wrapper class. The managed wrapper class uses GetDelegateForFunctionPointer, which works to marshal static native pointers to a delegate, but I can't find any information if it works with instances. GetDelegateForFunctionPointer also takes a System::IntPtr argument for the function pointer, but I'm also not sure if System::IntPtr works for instances, and when compiling in VC++2008 I'm being presented an error C3867 for attempting this.
Managed wrapper header:
//somemanagedclass.hpp
#pragma once
using namespace System;
using namespace ExternalManagedLibrary;
namespace SomeNameSpace
{
public ref class SomeManagedClass
{
public:
SomeManagedClass();
~SomeManagedClass();
delegate void CallbackHandler(const wchar_t*, int);
CallbackHandler^ CallbackEvent;
void RegisterCallback(IntPtr callbackEvent);
private:
ExternalManagedClass^ externalManagedClass;
void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
};
}
Managed wrapper source:
//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace System;
using namespace Runtime::InteropServices;
namespace SomeNameSpace
{
SomeManagedClass::SomeManagedClass()
{
externalManagedClass = gcnew ExternalManagedClass();
externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
SomeManagedClass::~SomeManagedClass()
{
externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
{
String^ some_string = String::Copy(e->Value);
cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
const wchar_t* p = pinned_string;
CallbackEvent(pinned_string, some_string->Length);
}
void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
{
CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
}
}
Native wrapper interface:
//somenativeinterface.hpp
#ifdef DLL_EXPORT
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT
typedef void (*NativeCallback)(const unsigned char*, unsigned long);
class IMPORT_EXPORT SomeNativeInterface
{
public:
//class factory
static SomeNativeInterface* Create(void);
static void Destroy(SomeNativeInterface* clInterface);
virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};
Native wrapper header:
//somenativeclass.hpp
#pragma once
#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace SomeNameSpace;
class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
public:
SomeNativeClass();
~SomeNativeClass();
void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?
private:
NativeCallback fnNativeCallback;
void OnNativeCallback(const wchar_t* cString, int iSize);
gcroot<SomeManagedClass^> wrapper; //warning C4251
};
Native wrapper source:
//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>
using namespace System;
using namespace Runtime::InteropServices;
SomeNativeInterface* SomeNativeInterface::Create()
{
return ((SomeNativeInterface*) new SomeNativeClass());
}
void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
delete instance;
}
SomeNativeClass::SomeNativeClass()
{
wrapper = gcnew SomeManagedClass();
}
SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
size_t iCharsConverted;
if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
{
if (iCharsConverted > 0xFFFFFFFF)
iCharsConverted = 0xFFFFFFFF; //truncate
fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
}
}
SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
fnNativeCallback = fnNativeCallbackInit;
wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}
I have an element that decodes a media type, mytype for example. I want to register the type so that the decodebin element can use my element if needed. I added the code for what I thought would work, but my type_find() function is never called. Any ideas on what I'm doing wrong? Here's what the code looks like:
#define MY_CAPS (gst_static_caps_get(&my_caps))
static GstStaticCaps my_caps = GST_STATIC_CAPS("audio/x-mycaps");
static gchar *my_exts[] = { "mtype", NULL };
static void type_find(GstTypeFind *_type_find, gpointer callback)
{
printf("Type Find Function\r\n");
gst_type_find_suggest(_type_find, GST_TYPE_FIND_POSSIBLE, gst_static_caps_get(&my_caps));
}
gboolean plugin_init(GstPlugin *plugin)
{
if(!gst_type_find_register(plugin, "mytype", GST_RANK_PRIMARY, type_find, my_exts, MY_CAPS, NULL, NULL))
return FALSE;
if(!gst_element_register(plugin, "myelement", GST_RANK_PRIMARY, MY_ELEMENT_TYPE)
return FALSE;
return(TRUE);
}
I am wrapping a C library using C++/CLI. The C library was designed to be used from an unmanaged C++ class. This means that the library functions accept a C++ object pointer and then provide that pointer back in callbacks. This enables the callback code to redirect requests to an appropriate event function in the calling C++ object.
The actual functions are quite involved, so I have simplified the problem space to just a few basic items:
// C library function signature
void CLibFunc(CLIBCALLBACK *callback, void *caller);
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C callback implementation
int CallBackImpl(int param1, void* caller)
{
// Need to call the ManagedCaller's EventFunction from here
// ???
}
// C++/CLI caller class
public ref class ManagedCaller
{
public:
void CallerFunction(void)
{
// Call the C library function
// Need to pass some kind of this class pointer that refers to this object
CLibFunc(CallBackImpl, ????);
}
void EventFunction(param1)
{
}
}
Now the C library functions need to be called from a managed C++ class. Under C++/CLI, the garbage collector moves objects around in memory, so passing a simple fixed pointer to the class does not work anymore. I can solve the problem by pinning the object, but that is not recommended because it leads to memory fragmentation. It seems that another option would be to use auto_gcroot pointers, but I am fairly new to managed C++ an I am not sure how to make this work.
Does anyone know how to make this work? What kind of pointer should be passed to the C function? How should the callback implementation redirect to the calling object's event function?
This just happens to be similar to something I'm in the middle of working on right now.
Here is an blog post on providing native callbacks using C++ classes: http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx
I'm not familiar with calling C++ member functions from C, but I have done an interface (abstract base) class to another C++ class for callbacks (similar to the article). Here is a basic example of what I am providing a bridge for:
// Interface (abstract base) class providing the callback
class IProvider {
public:
virtual ~IProvider() {}
virtual void Callback() = 0;
};
// User class of the callback
class CUser {
IProvider * m_pProvider;
public:
CUser(IProvider * pProvider) {
m_pProvider = pProvider;
}
void DoSomething() {
m_pProvider->Callback();
}
};
// Implementation of the interface class
class CHelloWorldProvider : public IProvider {
void Callback() {
printf("Hello World!");
}
};
// Usage of the callback provider in a pure native setting
void PureNativeUsage() {
CHelloWorldProvider oProvider;
CUser oUser(&oProvider);
oUser.DoSomething();
}
Now in order to make this available for managed implementations of the provider, we have to create a series of classes that provide the bridge.
// Where gcroot is defined
#include <vcclr.h>
// Managed provider interface class
public interface class IManagedProvider {
void Callback();
};
// Native bridge class that can be passed to the user
class CProviderBridge : public IProvider {
// Give the managed class full access
friend ref class ManagedProviderBase;
// Store a reference to the managed object for callback redirects
gcroot<IManagedProvider ^> m_rManaged;
public:
void Callback(){
m_rManaged->Callback();
}
};
// Managed provider base class, this provides a managed base class for extending
public ref class ManagedProviderBase abstract : public IManagedProvider {
// Pointer to the native bridge object
CProviderBridge * m_pNative;
protected:
ManagedProviderBase() {
// Create the native bridge object and set the managed reference
m_pNative = new CProviderBridge();
m_pNative->m_rManaged = this;
}
public:
~ManagedProviderBase() {
delete m_pNative;
}
// Returns a pointer to the native provider object
IProvider * GetProvider() {
return m_pNative;
}
// Makes the deriving class implement the function
virtual void Callback() = 0;
};
// Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net)
public ref class ManagedHelloWorldProvider : public ManagedProviderBase {
public:
virtual void Callback() override {
Console::Write("Hello World");
}
};
// Usage of the managed provider from the native user
void MixedUsage() {
ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider;
CUser oUser(rManagedProvider->GetProvider());
oUser.DoSomething();
}
Edit: Added code to show w/o the managed interface class example I use.
Here is a modified version of my example that can be used given your CLibFunc above. This is assuming how the C function performs the callback is accurate.
Also this might be able to be slimmed down a bit depending on how involved your callback classes are and how much freedom for extension you need.
// Where gcroot is defined
#include <vcclr.h>
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C library function
void CLibFunc(CLIBCALLBACK *callback, void *caller) {
// Do some work
(*callback)(1234, caller);
// Do more work
}
// Managed caller interface class
public interface class IManagedCaller {
void EventFunction(int param1);
};
// C++ native bridge struct
struct CCallerBridge {
// Give the managed class full access
friend ref class ManagedCaller;
// Store a reference to the managed object for callback redirects
gcroot<IManagedCaller ^> m_rManaged;
public:
// Cast the caller to the native bridge and call managed event function
// Note: This must be __stdcall to prevent function call stack corruption
static int __stdcall CallBackImpl(int param1, void * caller) {
CCallerBridge * pCaller = (CCallerBridge *) caller;
pCaller->m_rManaged->EventFunction(param1);
return 0;
}
};
// C++/CLI caller class
public ref class ManagedCaller : public IManagedCaller {
// Pointer to the native bridge object
CCallerBridge * m_pNative;
public:
ManagedCaller() {
// Create the native bridge object and set the managed reference
m_pNative = new CCallerBridge();
m_pNative->m_rManaged = this;
}
~ManagedCaller() {
delete m_pNative;
}
// Calls the C library function
void CallerFunction() {
CLibFunc(CCallerBridge::CallBackImpl, m_pNative);
}
// Managed callback function
virtual void EventFunction(int param1) {
Console::WriteLine(param1);
}
};
// Usage
int main(array<System::String ^> ^args) {
ManagedCaller ^ oCaller = gcnew ManagedCaller();
oCaller->CallerFunction();
return 0;
}