Call c++ function pointer from c# - c#

Is it possible to call a c(++) static function pointer (not a delegate) like this
typedef int (*MyCppFunc)(void* SomeObject);
from c#?
void CallFromCSharp(MyCppFunc funcptr, IntPtr param)
{
funcptr(param);
}
I need to be able to callback from c# into some old c++ classes. C++ is managed, but the classes are not ref classes (yet).
So far I got no idea how to call a c++ function pointer from c#, is it possible?

dtb is right. Here a more detailed example for Marshal.GetDelegateForFunctionPointer. It should work for you.
In C++:
static int __stdcall SomeFunction(void* someObject, void* someParam)
{
CSomeClass* o = (CSomeClass*)someObject;
return o->MemberFunction(someParam);
}
int main()
{
CSomeClass o;
void* p = 0;
CSharp::Function(System::IntPtr(SomeFunction), System::IntPtr(&o), System::IntPtr(p));
}
In C#:
public class CSharp
{
delegate int CFuncDelegate(IntPtr Obj, IntPtr Arg);
public static void Function(IntPtr CFunc, IntPtr Obj, IntPtr Arg)
{
CFuncDelegate func = (CFuncDelegate)Marshal.GetDelegateForFunctionPointer(CFunc, typeof(CFuncDelegate));
int rc = func(Obj, Arg);
}
}

Have a look at the Marshal.GetDelegateForFunctionPointer method.
delegate void MyCppFunc(IntPtr someObject);
MyCppFunc csharpfuncptr =
(MyCppFunc)Marshal.GetDelegateForFunctionPointer(funcptr, typeof(MyCppFunc));
csharpfuncptr(param);
I don't know if this really works with your C++ method, though, as the MSDN documentation states:
You cannot use this method with function pointers obtained through C++

Related

Call unmanaged fastcall C function by address in C#

I'm injecting my C# dll into an unmanaged process written in C. How would I go about calling a function in this process? I know the address of the function and the function signature. The function uses fastcall calling convention. I'm not sure if this complicates things.
I have tried using delegates like so:
[UnmanagedFunctionPointer(CallingConvention.FastCall, CharSet = CharSet.Unicode)]
public delegate IntPtr _PrintText(string msg, int color);
Which raises a warning about FastCall not being supported.
Here's a more complete, simple example of what I've tried:
C++ function:
void __fastcall PrintText (wchar_t * wMessage, int nColor)
Address: 0x31E3A0
C# code:
public class Example
{
[UnmanagedFunctionPointer(CallingConvention.FastCall, CharSet = CharSet.Unicode)]
public delegate IntPtr _PrintText(string msg, int color);
public static int EntryPoint(string pwzArgument)
{
var ptr = new IntPtr(0x31E3A0);
_PrintText MyPrint = Marshal.GetDelegateForFunctionPointer<_PrintText>(ptr);
MyPrint("TESTING", 0);
}
}
How do I properly define and call a FastCall C function using C#?

Call C++ native/unmanaged member functions from C# when member functions were not exported

I have an unmanaged DLL that exports only a C style factory method that returns a new instance of a class (simplified here to look simple).
hello.h
#if defined(HWLIBRARY_EXPORT) // inside DLL
# define HWAPI __declspec(dllexport)
#else // outside DLL
# define HWAPI __declspec(dllimport)
#endif
struct HelloWorld{
public:
virtual void sayHello() = 0;
virtual void release() = 0;
};
extern "C" HWAPI HelloWorld* GetHW();
hello.cpp
#include "hello.h"
struct HelloWorldImpl : HelloWorld
{
void sayHello(){
int triv;
std::cout<<"Hello World!";
std::cin>>triv;
};
void release(){
this->HelloWorldImpl::~HelloWorldImpl();
};
HelloWorld* GetHW(){
HelloWorld* ptr = new HelloWorldImpl();
return ptr;
};
Now, I can use dllimport to access GetHW() but is there a way to access the member functions of the returned 'struct'... ie, sayHello and release?
I was also stuck with the same problem. This question was asked a while before. I commented to it for any better solution but didn't get any reply yet. So, reposting it.
When i googled, able to find out two solutions.
Solution1: Expose all the member functions in the C-style for the existing dll. Which i cant do, as it is a 3rd party dll.
Solution2: Write a managed C++ dll exposing the functionality of native C++ dll, which later can be used in your C# dll. Here many classes/functions are present. So, creating would take most of the time.
i got the above solutions from the link below.
How To Marshall
Please let me know if there is any better solution other than the above two solutions?
i have the source code for C++ solution. But what i though was not to touch C++ dll. If there is any possibility to do it in C#, it would be great.
If there is no alternative, i need to follow any one of the specified two solutions.
The C++ code is using the way abstract classes are implemented by the Visual C++ compiler. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx. This memory layout is "fixed" because it is used for implementing COM interfaces. The first member of the struct in memory will be a pointer to a vtable containing the function pointers of your methods. So for a
struct HelloWorldImpl : public HelloWorld
{
public:
int value1;
int value2;
}
the "real" layout in memory would be:
struct HelloWorldImpl
{
HelloWorldVtbl *vtbl;
int value1;
int value2;
}
where vtbl would be:
struct HelloWorldVtbl
{
void *sayHello;
void *release;
}
Just for the sake of doing a complete response, I'm writing the example for this signatures:
struct HelloWorld {
public:
virtual int sayHello(int v1, int v2, int v3) = 0;
virtual void release() = 0;
};
C# code:
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetHW();
[StructLayout(LayoutKind.Sequential)]
struct HelloWorldVtbl
{
public IntPtr sayHello;
public IntPtr release;
}
Your functions are void Func(void) or int Func(int, int, int), but in truth they have a hidden parameter, this, so you can write them as:
int sayHello(HelloWorld*, int, int, int);
void release(HelloWorld*);
so in C# the delegate is
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate int Int32MethodInt32Int32Int32(IntPtr ptr, int v1, int v2, int v3);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void VoidMethodVoid(IntPtr ptr);
Then you can use
IntPtr ptr = GetHW();
IntPtr vtbl = Marshal.ReadIntPtr(ptr, 0);
HelloWorldVtblhw = (HelloWorldVtbl)Marshal.PtrToStructure(vtbl, typeof(HelloWorldVtbl));
Int32MethodInt32Int32Int32 sayHello = (Int32MethodInt32Int32Int32)Marshal.GetDelegateForFunctionPointer(hw.sayHello, typeof(Int32MethodInt32Int32Int32));
int res = sayHello(ptr, 1, 2, 3);
Console.WriteLine(res);
VoidMethodVoid release = (VoidMethodVoid)Marshal.GetDelegateForFunctionPointer(hw.release, typeof(VoidMethodVoid));
release(ptr);

Pass callback argument from C# to unmanaged C++

I have some of unmanaged C++ dynamic library and C# GUI application, using it. I want to pass callback via parameters in some library provided methods. Is it possible to pass a callback to unmanaged C++ method from C#.
// unmanaged C++
typedef uint8_t (__stdcall *SomeCallback)();
MYDLL_API uint8_t someMethod(SomeCallback cb);
I'm trying to use library in this way:
// C# part
public delegate Byte SomeDelegate();
[DllImport("mylibraryname.dll")]
public static extern Byte someMethod(ref SomeDelegate pDelegate);
// actuak callback
Byte myCallback() {
// some code
}
...
// call unmanaged passing callback
static void Main(string[] args) {
someMethod(myCallback);
}
I receive error on compilation:
cannot convert from 'method group' to 'ref SomeDelegate
Am I totally wrong with my approach?
It is because you MUST put the ref modifier before the argument and that forces the it to be a variable. so:
change you extern to:
public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)]
ref SomeDelegate pDelegate);
and your call to:
SomeDelegate action = new SomeDelegate(myCallback);
someMethod(ref action);
UPDATE: And if you want to pass an argument to the callback (say an int):
public delegate Byte SomeDelegate([MarshalAs(UnmanagedType.I4)] int value);
[DllImport("mylibraryname.dll")]
public static extern Byte someMethod([MarshalAs(UnmanagedType.FunctionPtr)]
ref SomeDelegate pDelegate);
Byte MyMethod([MarshalAs(UnmanagedType.I4)] int value)
{
return (byte) (value & 0xFF);
}
and calling:
SomeDelegate action = new SomeDelegate(MyMethod);
someMethod(ref action);
Update to C# code for .NET 4.8:
public delegate Byte SomeDelegate(int value);
[DllImport("mylibraryname.dll")]
public static extern Byte someMethod(IntPtr pDelegate);
Byte MyMethod([MarshalAs(int value)
{
return (byte) (value & 0xFF);
}
calling:
SomeDelegate myCallback = new SomeDelegate(MyMethod);
someMethod(Marshal.GetFunctionPointerForDelegate(myCallback));

Why does my program crash immediately after calling delegate?

I'm trying to wrap this function defined by SDL2.
It's signature is
void SDL_AddEventWatch(SDL_EventFilter filter, void* userdata)
Where SDL_EventFilter is
typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
Thus, I've defined my wrapper like so:
public delegate int EventFilter(IntPtr userData, IntPtr type);
[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch")]
public static extern void AddEventWatch(EventFilter filter, IntPtr userData);
And I'm testing it like so:
SDL.AddEventWatch((data, e) =>
{
return 0;
}, IntPtr.Zero);
When I run my program it actually enters the lambda function, but then immediately crashes as soon as it exits the function ("vshost32.exe has stopped working").
What might be causing the crash?
#define SDLCALL __cdecl
You have a calling convention mismatch. Your native code requires a __cdecl function but your C# code declares a delegate that will be mapped to a an __stdcall callback. The default for unmanaged code interop. You must declare it like this:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int EventFilter(IntPtr userData, IntPtr type);

C# Interop: Out params that can also be null

Consider the following DllImport:
[DllImport("lulz.so")]
public static extern int DoSomething(IntPtr SomeParam);
This is actually referencing a C style function like this:
int DoSomething(void* SomeParam);
Consider that SomeParam is an "out" param, but can also be NULL. The C function behaves differently if the param is NULL. So I would probably want:
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
But, if I make it an out param in my import, I cannot pass it NULL, i.e. I can't do this:
int retVal = DoSomething(IntPtr.Zero)
What are my options here?
If you're trying to pass a value, then out is not the right keyword; change it to ref. You'll still need to explicitly pass a variable, but it can be a null reference.
For example...
[DllImport("lulz.so")]
public static extern int DoSomething(ref IntPtr SomeParam);
You can then call it like this:
IntPtr retVal = IntPtr.Zero;
DoSomething(ref retVal);
However
What is telling you that it needs to be either out or ref? Passing an IntPtr as out or ref is really akin to passing a double pointer. It would actually seem more appropriate to pass the parameter as an IntPtr.
The typical procedure is either to allocate the necessary memory in managed code and pass an IntPtr representing that allocated memory, or IntPtr.Zero to represent a null pointer. You do not need to pass the IntPtr as out or ref in order to send data back to .NET; you only need to do that if the function you're calling would actually change the pointer's address.
I don't understand what the problem is....
This runs:
private void button2_Click(object sender, EventArgs e) {
object bar;
Method(out bar);
bar = IntPtr.Zero;
Method(out bar);
}
private void Method(out object foo) {
foo = null;
}
What's the intention of passing NULL? Is it intended to call the method as usual, but to simply not set the output parameter?
In that case, I think I'd just wrap the extern method with an overload in C#. That overload (without the out parameter) would be like this:
public void DoSomething()
{
IntPtr dummy;
DoSomething(out dummy);
}
I ran into this once. I ended up marshaling the pointer myself (see Marshal Members for the library functions to do so).
Personally, I'd import this function twice, first time with 'out' parameter, second with 'in'.
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
// call as DoSomethingWithNull(IntPtr.Zero)
[DllImport("lulz.so", EntryPoint="DoSomething")]
public static extern int DoSomethingWithNull(IntPtr SomeParam);
This will solve your problem and will make code more readable.

Categories