如何在OSX上使用GetDelegateForFunctionPointer在C#中调用外部符号?

时间:2015-03-08 13:21:43

标签: c# pinvoke

有一些人在询问如何使用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;
}

......最后,如果你要对这个问题进行投票,请至少留下反馈,说明为什么这个问题不好。

0 个答案:

没有答案