2011-02-22 81 views
3

我使用monotouch将一些C#代码嵌入到iphone objective-c应用程序中。我可以调用C#代码并获得返回值,但我无法使用PInvoke从C#代码调用C函数。我试图找到一个简单的例子工作。这是一个简单的计算器。目标c代码调用C#代码来添加两个整数。然后,C#代码应该回调到objective-c代码中并给它更新的值。下面是处理计算的C#代码:Monotouch PInvoke System.EntryPointNotFoundException

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当调试我得到以下输出。它看起来像它找到的方法再不能找到它:

单声道:的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编译代码(wrapper managed-to-native)Math.MyClass:updateResult(int)0x3bc8 - 0x3d90 0x3dcb

单声道:DllImport试图加载:'__Internal'.Mono:Se 'updateResult'.Mono:探测'updateResult'.Mono:探测'updateResult'.Mono:探测'updateResultA'.Mono:探测'updateResultA'.Unable解决pinvoke方法'Math.MyClass:updateResult(int)'Re使用MONO_LOG_LEVEL = debug运行以获取更多信息。

我花了一段时间试图弄清楚这一点。从我读过的内容看来,这应该是相当微不足道的,但我无法让它工作。任何帮助将非常感激。

回答

1

使用Selectors会更好吗?

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

+0

上提供一个测试用例的bug。我可以通过使用选择。另一种方式似乎更简单,这就是为什么我首先去了它。 – BLeB 2011-02-23 19:26:14

1

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

+0

我在项目设置的链接部分取消选中“死代码剥离”。我不确定这是否是您所说的确切选项,但这似乎没有改变任何事情。我也尝试关闭优化而没有成功。我可以在二进制文件上运行nm命令,并在那里看到updateResult符号。 – BLeB 2011-02-23 16:19:45

+0

一切看起来都很好,而且“selector”方法总是使用pinvoke,所以别的地方是错误的,随时在http://monotouch.net/Support – 2011-02-23 19:30:10

1

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