Monotouch PInvoke System.EntryPointNotFoundException

时间:2011-02-22 23:59:42

标签: iphone pinvoke xamarin.ios

我使用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);
}

这是我的代码,它初始化mono并处理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环境变量设置为debug我在尝试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:探测'updateResultA'.Mono:AOT FOUND AOT编译代码(包装托管到原生)Math.MyClass:updateResult(int)0x3bc8 - 0x3d90 0x3dcb

     

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

我花了很多时间试图解决这个问题。从我所看到的情况看来,这应该是非常微不足道的,但我无法让它发挥作用。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

使用Selectors会不会更好?

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

答案 2 :(得分:1)

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