admin管理员组文章数量:1417395
Looking for some pointers (no pun intended...) as to the best approach for this scenario.
So, I have a DLL (Provided Externally) that has the following exported function:
typedef std::function<void (
unsigned int msgType,
unsigned int size,
const char* const value
) > SCallback;
__declspec(dllexport) int StartS( SCallback fnS );
I'm attempting to call this from a C# Console Application, and this is what I am doing:
[DllImport("SeqLib.dll", EntryPoint = "?StartS@SApi@@YAKV?$function@$$A6AXIIPBD@Z@std@@@Z", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int StartS(DCallback cb);
public delegate void DCallback(int msgType, int size, IntPtr value);
public static void MessageReceived(int msgType, int size, IntPtr value)
{
return 0;
}
DCallback callback = new DCallback(MessageReceived);
StartS(callback);
Running this gives:
System.AccessViolationException: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Exception aside, is there something wrong with the basic approach above? Can anyone advise on the correct approach to calling an exported function that has a std::function parameter as above?
Thanks in advance.
Looking for some pointers (no pun intended...) as to the best approach for this scenario.
So, I have a DLL (Provided Externally) that has the following exported function:
typedef std::function<void (
unsigned int msgType,
unsigned int size,
const char* const value
) > SCallback;
__declspec(dllexport) int StartS( SCallback fnS );
I'm attempting to call this from a C# Console Application, and this is what I am doing:
[DllImport("SeqLib.dll", EntryPoint = "?StartS@SApi@@YAKV?$function@$$A6AXIIPBD@Z@std@@@Z", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int StartS(DCallback cb);
public delegate void DCallback(int msgType, int size, IntPtr value);
public static void MessageReceived(int msgType, int size, IntPtr value)
{
return 0;
}
DCallback callback = new DCallback(MessageReceived);
StartS(callback);
Running this gives:
System.AccessViolationException: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Exception aside, is there something wrong with the basic approach above? Can anyone advise on the correct approach to calling an exported function that has a std::function parameter as above?
Thanks in advance.
Share Improve this question asked Jan 31 at 10:29 MikeMike 5654 silver badges12 bronze badges 5 |1 Answer
Reset to default -2You need to use extern "C"
to prevent name mangling. And you need to specify the calling convention on the delegate.
You should also use string
on the value
parameter and marshal it properly
extern "C" {
__declspec(dllexport) int StartS( SCallback fnS );
}
And in C#
[DllImport("SeqLib.dll", EntryPoint = "StartS", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int StartS(DCallback cb);
[UnamangedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate void DCallback(int msgType, int size, string value);
If the C++ side holds on to the function pointer in global state past the end of the function then you need to keep the delegate alive. For example, put it into a field.
private DCallback _callback = MessageReceived;
private void SetCallback()
{
_ = StartS(callback);
}
Note that C# cannot handle C++ objects such as smart pointers and classes. You must only use basic types such as numbers, string pointers and array pointers. C# also can't usually free the pointers correctly, you'd need to free them on the C++ side.
本文标签: How to call stdfunction within an unmanaged C DLL from CStack Overflow
版权声明:本文标题:How to call std::function within an unmanaged C++ DLL from C#? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745268526a2650749.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
extern "C"
to prevent name mangling. @PepijnKramer That is really not correct, it's perfectly possible to use C++ functions, you just need to prevent mangling and not use C++ objects (as C++ can't interact or destroy them) – Charlieface Commented Jan 31 at 12:06