有一些人在询问如何使用dl
库在非Windows系统上动态加载和调用C#中的插件。
一般来说,建议似乎是使用GetDelegateForFunctionPointer'。但是,没有人能够提供加载的实际工作示例外部库 AND 调用它。
以下代码:
class Helper
{
const int RTLD_NOW = 2;
[DllImport("dl")]
static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)] string filename, int flags);
[DllImport("dl")]
static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] string symbol);
public static void Test() {
IntPtr libraryHandle = dlopen("libextern.dylib", RTLD_NOW);
IntPtr action = dlsym(libraryHandle, "rs_trigger");
var caller = (rs_trigger) Marshal.GetDelegateForFunctionPointer(action, typeof(rs_trigger));
var r = caller(1);
log ("Success! " + libraryHandle + " .. " + action + " --> " + r);
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int rs_trigger(int value);
}
打印:
Success! 105553117399168 .. 6120303264 --> 1339432
但是,调用的c代码中的rs_trigger不返回1339432.使用python和ctypes调用库显示:
Python 2.7.9 (default, Jan 29 2015, 06:27:40)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> lib = ctypes.CDLL("libextern.dylib")
>>> lib
<CDLL 'libextern.dylib', handle 7f7f83601e60 at 10b389550>
>>> lib.rs_trigger
<_FuncPtr object at 0x10b367940>
>>> lib.rs_trigger(1)
Trigger called
Invoking callback
No callback bound
101
>>> lib.rs_trigger(100)
Trigger called
Nope
200
>>> output = lib.rs_trigger(100)
Trigger called
Nope
>>> output
200
显然,C#call caller(1)
正在将格式错误的数据传递给c函数调用...但我在过去一小时内已经阅读了很多示例,并且他们似乎都在说正好这样。
我做错了什么?
完全是用于您定义的委托的语法,以将IntPtr绑定到外部函数调用来调用它?
(注意。一切都是x86_64,这绝不是问题)
这是c代码:
#include <stdio.h>
#ifdef _WIN64
#define __EXT __declspec(dllexport)
#elif _WIN32
#define __EXT __declspec(dllexport)
#else
#define __EXT extern
#endif
static void (*callback)(int value) = NULL;
__EXT int rs_trigger(int val) {
printf("Trigger called\n");
if (val == 1) {
printf("Invoking callback\n");
if (callback != NULL) {
(*callback)(100);
}
else {
printf("No callback bound\n");
}
}
else {
printf("Nope\n");
}
return val + 100;
}
__EXT void rs_register(void *cb) {
printf("Register called\n");
callback = cb;
}
......最后,如果你要对这个问题进行投票,请至少留下反馈,说明为什么这个问题不好。