Monotouch PInvoke System.EntryPointNotFoundException

Posted

技术标签:

【中文标题】Monotouch PInvoke System.EntryPointNotFoundException【英文标题】: 【发布时间】:2011-02-22 23:59:42 【问题描述】:

我使用 monotouch 将一些 C# 代码嵌入到 iphone Objective-c 应用程序中。我能够调用 C# 代码并获取返回值,但我无法使用 PInvoke 从 C# 代码调用 C 函数。我试图让一个简单的例子起作用。这是一个简单的计算器。目标 c 代码调用 C# 代码以添加两个整数。然后,C# 代码应回调到 Objective-c 代码并为其提供更新的值。下面是处理计算的 C# 代码:

public class MyClass
       
    static public void Add(int a, int b)
    
        updateResult(a + b);
    

    [DllImport("__Internal", EntryPoint="updateResult")]
    static extern public void updateResult(int result);

这是我初始化单声道并处理 add 方法的代码:

@implementation Mono

- (id)init 
self = [super init];

if (self) 
    NSBundle *main = [NSBundle mainBundle];
    NSString *path = [main bundlePath];
    const char *c_path = [path UTF8String];

    [main autorelease];
    [path autorelease];

    chdir (c_path);
    setenv ("MONO_PATH", c_path, 1);
    setenv ("MONO_XMLSERIALIZER_THS", "no", 1);
    setenv ("DYLD_BIND_AT_LAUNCH", "1", 1);
    setenv ("MONO_REFLECTION_SERIALIZER", "yes", 1);

#if defined (__arm__)
    mono_aot_register_module (mono_aot_module_mscorlib_info);
    mono_aot_register_module (mono_aot_module_Math_info);

    mono_jit_set_aot_only (TRUE);
#endif
    mono_jit_init("MonoTouch");
    MonoAssembly *assembly = mono_assembly_open("Math.dll", NULL);
    MonoImage *img = mono_assembly_get_image(assembly);
    MonoClass *cls = mono_class_from_name(img, "Math", "MyClass");
    MonoMethodDesc *methodDesc = mono_method_desc_new("Math.MyClass:Add", TRUE);
    _addMethod = mono_method_desc_search_in_class(methodDesc, cls);


return self;
 

- (void)addA:(int)a plusB:(int)b 
    void *params[] =  &a, &b ;
    mono_runtime_invoke(_addMethod, NULL, params, NULL);


@end

这里是updateResults方法的定义:

extern void updateResult(int result) 
    printf("Got Result");

当从 C# 端调用 updateResults 时,我得到以下异常:

Unhandled Exception: System.EntryPointNotFoundException: updateResult
at (wrapper managed-to-native) Math.MyClass:updateResult (int)
at Math.MyClass.Add (Int32 a, Int32 b) [0x00000] in <filename unknown>:0 

我可以使用以下命令在二进制文件中看到该符号:

$ nm Calc | grep updateResult
00002b2e t _updateResult

将 MONO_LOG_LEVEL 环境变量设置为调试我在尝试 PInvoke 时得到以下输出。貌似找到了方法然后找不到了:

Mono:DllImport 试图加载:'_Internal'。Mono:搜索“updateResult”。Mono:探测“updateResult”。Mono:探测“updateResult”。Mono:探测“updateResultA”。Mono:探测'updateResultA'.Mono: DllImport 试图加载:'_Internal'.Mono: 搜索'updateResult'.Mono: 探测'updateResult'.Mono: 探测'updateResult'.Mono: 探测'updateResultA'.Mono: Probing 'updateResultA'.Mono: AOT FOUND AOT 编译代码(包装器托管到本机)Math.MyClass:updateResult (int) 0x3bc8 - 0x3d90 0x3dcb

Mono:DllImport 试图加载:'__Internal'。Mono:搜索'updateResult'。Mono:探测'updateResult'。Mono:探测'updateResult'。Mono:探测'updateResultA'。Mono:探测'updateResultA'。无法解析 pinvoke 方法 'Math.MyClass:updateResult (int)' 使用 MONO_LOG_LEVEL=debug 重新运行以获取更多信息。

我花了很长时间试图弄清楚这一点。从我读过的内容来看,这似乎应该是微不足道的,但我无法让它发挥作用。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

使用Selectors会更好吗?

这是 MonoTouch 制造商建议的默认路径。

【讨论】:

我能够通过使用选择器让它工作。另一种方法似乎更简单,这就是我先选择它的原因。【参考方案2】:

这可能是一些事情,但我的第一个猜测是您没有在本机代码的任何地方使用 C 符号,并且 DCE(死代码消除)通过正在删除它。尝试在 Xcode 项目选项中禁用 DCE。

【讨论】:

我在项目设置的链接部分取消了“死代码剥离”的勾选。我不确定这是否是您所说的确切选项,但这似乎并没有改变任何东西。我也尝试关闭优化但没有成功。我可以在二进制文件上运行 nm 命令并在那里看到 updateResult 符号。 一切看起来都很好,并且“选择器”方法无论如何都使用 pinvoke,所以还有其他问题,请随时在monotouch.net/Support@ 提交测试用例的错误【参考方案3】:

我自己也遇到过这个问题,如果你比较二进制文件的 objdump -T 和 objdump -t, 您会发现“D”标志丢失了,因此请在链接器选项中添加 -rdynamic。

【讨论】:

以上是关于Monotouch PInvoke System.EntryPointNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MonoTouch 中使用 System.IO.Packaging

System.Net.NetworkInformation IPv4Mask 在 MonoTouch 中不起作用?

如何使用 MonoTouch 以短时间格式将 DateTime 格式化为本地用户区域设置

C# Marshal / Pinvoke CBitmap?

C# - 方法的类型签名与 PInvoke 不兼容。使用 MarshalDirectiveException

MonoTouch 4.0 使用模拟器抛出 ReflectionTypeLoadException