How to create lambda-wrapper around C-style callback? - c#

I have such layers: C# main application -- CLI/C++ wrapper for C++ library -- C++ library.
CLI middle layer was written because of the limitations of C#-C++ interoperability. I used it also to polish some rough edges from C# point of view -- in other words, the middle layer allows to hide C/C++ types (like char*) and do all necessary conversions.
One conversion I fail to make is passing a callback. I tried to do it as in Pass a c++ lambda to old c function pointer but I cannot pass a lambda as a callback.
C++ callback definition:
typedef void (*CppOnEngineCloseCallback)
(void * customParam, const wchar_t * errorMessage);
I know customParam is not used, so I define such callback for middle layer (CLI/C++):
typedef void (*CLIOnEngineCloseCallback)
( String ^ errorMessage);
In the wrapper I create such lambda:
// lambda signature should resemble CppOnEngineCloseCallback
auto lambda = [&] (void * customParam, const wchar_t * errorMessage) {
cli_callback(Marshal::PtrToStringUni( IntPtr(static_cast<void*>(
const_cast<wchar_t*>(errorMessage)))));
};
My concern is if cli_callback will be properly kept in CLI environment (this is my first project) -- after all, I pass it in time A, and use it in time B.
Compiler has even stronger concern, because when I try to use the lambda:
InitEngine( // C++ function that requires callback
&lambda);
it says it cannot convert lambda into CppOnEngineCloseCallback.
Is it doable in the first place? How?

You're using auto, hence you're hiding the actual type, and making it harder on yourself to manage the C++ strongly typed type safety.
Probably the lambda function isn't the right type, or at least not the type you're expecting.
CppOnEngineCloseCallback is probably a function pointer type (or std::funciton type).
So, to help yourself, try changing the lambda's type to the expected type, and see what the compiler says.
CppOnEngineCloseCallback lambda = [&] (void * customParam, const wchar_t * errorMessage) {
cli_callback(Marshal::PtrToStringUni( IntPtr(static_cast<void*>(
const_cast<wchar_t*>(errorMessage)))));
};
The InitEngine() method expects a CppOnEngineCloseCallback, so you must make sure it gets it.
Besides that, you can only assign a lambda with empty brackets [] to a function pointer. In your case you're not using anything from the local scope, hence you don't really need [&].
Lambda functions : operator ret(*)(params)()
This user-defined conversion function is only defined if the capture
list of the lambda-expression is empty.
If you do want to use this kind of lambda expression, you'll have to use std::function instead of a function pointer:
typedef std::function<void(void *, const wchar_t *)> CppOnEngineCloseCallback;

In general, it is not possible, to cast a lambda to a function pointer.
As you know, a lambda is an object of a compiler generated class, that only behaves like a function.
For your actual problem: you mentioned that customParam is not used.
A typical pattern is, that customParam is provided by the caller of the library and used in the callback function to identify some object handling the callback. Inside the callback, you then map to the function you actually want to call:
void MyNativeCallback(void * customParam, const wchar_t * errorMessage)
{
static_cast<MyClass*>(customParam)->Callback(errorMessage);
}
So you could pass a pointer to your lambda as customParam to the library, and provide a helper function as above as callback. Anyways, getting the pointer types correctly will not be a simple task. I would prefer a small helper class instead.

Related

Marshal out parameter that is a reference type

I'm trying to get a C# class (not struct!) from a C++ function back (using out parameter). This is the C# side:
[StructLayout(LayoutKind.Sequential)]
public class OutClass
{
public int X;
}
// This interface function will be mapped to the C++ function
void MarshalOutClass(out OutClass outClass);
The C++ part looks like this
struct OutClass
{
int x = 0;
};
extern "C" MARSHAL_TESTS_API void MarshalOutClass(OutClass** out);
The function mapping works via a custom mechanism and is not part of this question. All marshaling attributes are treated normally.
In C#, we usually declare out arguments inline, like:
MarshalOutClass(out var outClass);
DoSomething(outClass);
Since C# reference types are marshaled by pointer, I figured I would have to add another pointer for ref or out parameters. So I use OutClass** on the C++ side.
I assume that C# translates the
MarshalOutClass(out var outClass);
part to roughly
OutClass outClass = default(OutClass);
MarshalOutClass(ref outClass);
which is a reference to null, or on C++ side: a pointer to a nullptr. This wouldn't be a problem for C# value types (aka struct) because their default is a default constructed instance.
This means, I'd have to manually create an instance of my object on the C++ side and marshal it back to C#.
void MarshalOutClass(OutClass** out)
{
auto ptr = static_cast<OutClass*>(CoTaskMemAlloc(sizeof(OutClass)));
*ptr = OutClass{};
*out = ptr;
}
The code seems to work, but I'm not sure if I'm leaking memory with this or if the marshaler is going to to take care of it properly. I don't do any cleanup on the C# side.
This brings me to the following questions:
is my assumption on how ref and out are translated to C++ correct?
is CoTaskMemAlloc the correct function here?
do I have to perform any additional memory management related tasks (on either side)?
is the overall approach correct here? What should I do differently?
I know that static_cast<OutClass*>(CoTaskMemAlloc(sizeof(OutClass))) is a bit sketchy here but lets assume OutClass is always a trivial type.

Set C Function Pointer to C# Function

I need to set a callback function in a C library equal to a C# function, and can't figure out a way to do it without either dlopen or kernel32, which seems windows/unix specific. Does anyone know of a way to do this?
The problem: C shared library exposes function pointers, whose values should be set by over-writing them. E.g.
//C Code
extern void (*ptr_R_ShowMessage) (const char *)
The current c# code creates a delegate to a function that matches this signature, uses the marshal class to get a pointer to that delegate, and then overwrites the C pointer with this value.
//call to libdl or kernel32.dll
IntPtr showPointer = GetFunctionAddress(hndl,"ptr_R_ShowMessage");
IntPtr newShowPointer = Marshal.GetFunctionPointerForDelegate(matchingDelegate);
Marshal.WriteIntPtr(showPointer, newShowPointer);
The requirement on libdl and kernel32.dll causes all kinds of problems... and ideally would be avoided.
Does anyone know how I can make the C libraries pointer point to the C# code, without modifying the C code or using the GetFunctionAddress dynamic loading? I think this might be impossible, but it seems like it could be.
I'm not 100% sure if this is what you're looking for.
In our case, we have a third party C Sdk that provides several hooks for callback messages. The callback call is initiated in C code and expects to invoke a C function, but we are able to hook it to a C# method using the following steps. (This code is kind of old and probably there are more succint and modern methods to accomplish the same in newer iterations of C#).
First we declare inside a C# class a Callback delegate, compatible with the signature of the C function pointer the SDK is expecting.
For example, if the C code is expecting to call back a function having the following signature:
void DecCallBack(int nPort, void* pBuf, int nSize, FRAME_INFO *pInfo, int nReserved1, int reserved 2);
Here's the matching C# delegate definition. Note that the "magic" happens thanks to the UnmanagedFunctionPointer attribute:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate void DecCallBack(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO frameInfo, int nReserved1, int nReserved2);
Once we have this, we declare a class member of type DecCallBack that will hold a delegate instance in our class.
static DecCallBack _decodeCallBack = null;
Next we code a handler method compatible with the delegate signature. In this case we name it HandleDecData()
private static void HandleDecData(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO frameInfo, int nReserved1, int nReserved2) {
// Here we handle the callback, this code is being called from an external C library
}
Next, somewhere in the C# class, we need to initialize the delegate member and hook our callback Handler (In this case it is the static method HandleDecData()
_decodeCallBack += new DecCallBack(HandleDecData);
Finally, we pass the delegate member as if it were a function pointer to C.
In our case, the third party SDK has a C PlayM4_SetDecCallBack() function that expects the function pointer to call when the callback is invoked - we can safely pass the delegate member of our class instead.
if( !PlayM4_SetDecCallBack(channel, _decodeCallBack) )
throw new InvalidOperationException("Error setting DecCallBack");
I hope this is helpful.
C shared library DO NOT exposes function pointers in that way, extern means that this function is defined in another C file and linker during creation of binary object will use actual code from the function in final executable
to fix this you need to include C# file somehow in C project in way the C compiler will link both into binary object, but it is impossible
what current code is trying to do is called "hack", if you want to achieve similar functionality without hacks you need:
In C code provide function which will accept pointer to function to execute
In C code where ptr_R_ShowMessage is called use pointer from p1
In C# code call function from P1 and provide method to call as argument
Here is sample I've found which executes function from external library and provide it C# function as callback: http://tutorials.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Win32_callbacks
I confirmed that this is not possible in C# directly, so interfacing with the libary load function is required. Thanks to both for answers though, definitely useful.

Function pointer as a parameter of COM method

I have created COM server in C++ that is used from C# application. Now I have to add one more method to my COM object and one of its parameter must be function pointer to callback function. C++ original function looks like this:
typedef int (__stdcall *tCallBackFunc)(int Param);
void MyFunc(void* CallBackFunc)
{
int Param;
//some code
((tCallBackFunc)(CallBackFunc))(Param); //call callback function
}
I need to add MyFunc as COM object method. VS VC++ "Add Method" dialog offers some predefined types for COM method parameter like "int*" or "bstr", I tried to define "CallBackFunc" parameter as "int*" type, but I was not able to make it work in C#:
public delegate int tCallBackFunc(int Param);
...
tCallBackFunc cb; //I will initialize it when it is compiled
MyCOMObject.MyFunc(cb); //cannot find any way to cast cb to "ref int"
It seems I use wrong approach, is there a fast way to declare function pointer as parameter of COM object method in C++ and then use it in C#?
The COM way is to make the parameter an interface pointer, and have the interface declare the callback function.
+1 for Frederik's answer.
#Michael: It will prove a lot easier than your imagined solution.
Especially with
object lifetimes
process boundaries
thread safety (apartment boundaries, IOW)
standards conformance (casting function pointers quickly enters the domain of Undefined Behaviour). Why should you worry? Standards conformance must concern you in case a compiler update introduces another optimization that makes your old (non-conformant) code break

Why are function pointers not considered object oriented?

In the C# language specifications it explicitly states:
Delegates are similar to the concept
of function pointers found in some
other languages, but unlike function
pointers, delegates are
object-oriented and type-safe.
I understand delegates need to be a little more flexible than pointers because .NET moves memory around. That's the only difference I'm aware of, but I am not sure how this would turn a delegate into in OO concept...?
What makes a function pointer not object oriented? Are pointers and function pointers equivalent?
Well, Wikipedia says that "object oriented" means using "features such as data abstraction, encapsulation, messaging, modularity, polymorphism, and inheritance." Lacking a better definition, let's go with that.
Function pointers don't contain data, they don't encapsulate implementation details, they neither send nor receive messages, they are not modular, they are not typically used in a polymorphic manner (though I suppose they could in theory be covariant and contravariant in their return and formal parameter types, as delegates now are in C# 4) and they do not participate in an inheritance hierarchy. They are not self-describing; you can't ask a function pointer for its type because it doesn't have one.
By contrast, delegates capture data -- they hold on to the receiver. They support messaging in the sense that you can "message" a delegate by calling its ToString or GetType or Invoke or BeginInvoke methods to tell it to do something, and it "messages" you back with the result. Delegate types can be restricted to certain accessibility domains if you choose to do so. They are self-describing objects that have metadata and at runtime know their own type. They can be combined with other delegates. They can be used polymorphically as System.MulticastDelegate or System.Delegate, the types from which they inherit. And they can be used polymorphically in the sense that in C# 4 delegate types may be covariant and contravariant in their return and parameter types.
I believe it is because, when you hold a delegate to a member method, the OO framework "knows" you are holding a reference to the holding object, whereas with function pointers, first of all function isn't necessarily a member method and second of all, if the function is a member methods, the OO framework doesn't know it has to prevent the owning object from being freed.
Function pointers are just memory addresses.
Delegates are objects that have methods and properties:
-BeginInvoke
-DynamicInvoke
-Invoke
-Method
-Target
etc.
I'll explain with C++ examples because it's a language where this problem is present (and solved another way).
A mere function pointer just holds the address of a function, nothing else.
Consider the function
void f(int x) { return; }
Now, a simple function pointer is declared and assigned like this:
void (*fptr)(int) = &f;
And you can use it simply:
foo(5); // calls f(5)
However, in an object oriented language we usually deal with member functions, not free functions. And this is where things get nasty. Consider the following class:
class C { void g(int x) { return; } };
Declaring a function pointer to C::g is done like this:
void (*C::gptr)(int) = &C::g;
The reason why we need a different syntax is that member functions have a hidden this parameter, thus their signature is different.
For the same reason, calling them is problematic. That this parameter needs a value, which means you need to have an instance. Calling a pointer to a member function is done like this:
C c;
(c.*gptr)(5); // calls c.g(5);
Aside from the weird syntax, the real problem with this is that you need to pass the object together with your function pointer when you really just want to pass around one thing.
The obvious idea is to encapsulate the two, and that's what a delegate is. This is why a delegate is considered more OOP. I have no idea why it is considered more type-safe (maybe because you can cast function pointers to void*).
BTW the C++ solution in C++0x is adopted from Boost. It is called std::function and std::bind and works like this:
std::function<void (C*, int)> d = std::bind(&c::g, &c);
d(5); // calls c.g(5);
A function pointer can have no knowledge of the instance it belongs to unless you pass it in explicitly - all function pointers are to static members. A delegate, on the other hand, can be a regular member of the class, and the correct instance of the object will be used when the delegate is invoked.
Suppose one wants to design a general purpose anyprintf method which can behave as either fprintf, sprintf, cprintf [console printf with color support]. One approach would be to have it accept a function that accepts a void* and a char along with a void* and a va_list; it should then for each character of output call the passed-in function, passing it the supplied pointer and the character to be output.
Given such a function, one could implement vsprintf and fprintf [ignoring their return values for simplicitly] via:
void fprint_function(void* data, char ch) { fputc( (FILE*)data, ch); }
void sprint_function(void* data, char ch) { char**p = (char**)data; *((*p)++) = ch; }
void fprint_function(void* data, char ch) { cputchar( ch); }
void vfprintf(FILE *f, va_list vp, const char *fmt, va_list vp)
{
vsanyprintf(fprint_function, (void*)f, st, vp);
}
void vsprintf(char *st, va_list vp, const char *fmt, va_list vp)
{
vsanyprintf(fprint_function, (void*)f, st, vp);
}
void vcprintf(va_list vp, const char *fmt, va_list vp)
{
vsanyprintf(cprint_function, (void*)0, st, vp);
}
Effectively, the combination of the function pointer and void* behave as a method. Unfortunately, there's no way for the compiler to ensure that the data which is passed in the void* will be of the form expected by the supplied function. C++ and other object-oriented language add in compile-time validation of such type consistency.

How are delegates in C# better than function pointers in C/C++?

The delegates in C# offer similar functionality as function pointers in C. I heard someone saying "C# delegates are actually better than function pointers in C". How come? Please explain with an example.
"Better" is subjective -- but the main differences are:
Type safety. A delegate is not only guaranteed to refer to a valid method, it is guaranteed to refer to a method with the correct signature.
It's a bound method pointer -- that is, the delegate can point to a specific object on which to call the delegate. Thus, an Action<string> delegate could refer to alice.GetName or bob.GetName rather than just Person.GetName. This might be similar to C++ "pointer to member" -- I'm not sure.
In addition, the C# language supports closures through delegates to anonymous methods and lambda expressions -- i.e. capturing local variables of the declaring procedure, which delegate can reference when it later gets executed. This isn't strictly speaking a feature of delegates -- it's enabled by the C# compiler doing some magic on anonymous methods and lambda expressions -- but it's still worth mentioning because it enables a lot of the functional idioms in C#.
EDIT: As CWF notes in comments, another possible advantage of C# delegates is that the delegate type declarations are easier for many people to read. This may be a matter of familiarity and experience, of course.
Pointers can always point to the wrong place :) I.e it can point to a non-function or an arbitrary place in memory.
But in terms of functionality, function pointers can do anything that delegates can do.
One thing that a delegate provides that a C/C++ function pointer doesn't is type safety. That is, in C/C++, you can shove a function pointer into a function pointer variable declared with the wrong function signature (or even an int a double or worse with appropriate coaxing), and the compiler will be happy to produce code that calls the function completely incorrectly. In C#, the type signature of the function must match the type signature of the delegate and also the way the delegate is ultimately called.
Many people refer to C# delegates as more "type-safe" than C++ function pointers and I really find it misleading. In reality they are no more type-safe that C++'s function pointers are. An example C++ code (compiled by MSVS 2005 SP1):
typedef int (*pfn) (int);
int f (int) {
return 0;
}
double d (int) {
return 1;
}
int main()
{
pfn p=f; // OK
p=d; // error C2440: '=' : cannot convert from 'double (__cdecl *)(int)' to 'pfn'
p=(pfn)d;
}
So as is seen from the example above unless one uses "dirty hacks" to "shut up" the compiler the type mismatch is easily detected and the compiler's message is easy to understand. So that is type-safety as I understand it.
Regarding the "boundness" of the member function pointers. Indeed, in C++ pointer-to-member is not bound, the member function pointer has to be applied to a
type variable that matches the member pointer's signature. An example:
class A {
public:
int f (int) {
return 2;
}
};
typedef int (A::*pmfn) (int);
int main()
{
pmfn p=&(A::f);
// Now call it.
A *a=new A;
(a->*p)(0); // Calls A::f
}
Again, everything is perfectly type safe.

Categories