Monotouch PInvoke System.EntryPointNotFoundException

发布于 2024-10-19 03:35:03 字数 3112 浏览 4 评论 0原文

我使用 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 环境变量进行调试 在尝试 PInvoke 时,我得到以下输出。看起来好像找到了方法,然后就找不到了:

Mono:DllImport 尝试加载:'_Internal'。Mono:搜索“updateResult”。Mono:探测“updateResult”。Mono:探测“updateResult”。Mono:探测“updateResultA”。Mono:探测“updateResultA”。Mono:探测“updateResult”。Mono:探测“updateResult”。Mono:探测“updateResultA”。 '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

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

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

I've embedded some C# code into an iphone objective-c app using monotouch. I'm able to call into the C# code and get a return value, but I am not able to invoke a C function from the C# code using PInvoke. I am attempting to get a trivial example working. It is a simple calculator. The objective c code calls into the C# code to add two integers. The C# code should then call back into the objective-c code and give it the updated value. Below is the C# code that handles the calculation:

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);
}

Here is my code that initializes mono and handles the add method:

@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

and here is the definition of the updateResults method:

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

When the updateResults is called from the C# side of things I get the following exception:

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 

I can see the symbol in the binary with the following command:

$ nm Calc | grep updateResult
00002b2e t _updateResult

Setting the MONO_LOG_LEVEL environment variable to debug I get the following output when attempting the PInvoke. It looks like it finds the method and then can't find it:

Mono: DllImport attempting to load: '_Internal'.Mono: Searching for 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResultA'.Mono: Probing 'updateResultA'.Mono: DllImport attempting to load: '_Internal'.Mono: Searching for 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResultA'.Mono: Probing 'updateResultA'.Mono: AOT FOUND AOT compiled code for (wrapper managed-to-native) Math.MyClass:updateResult (int) 0x3bc8 - 0x3d90 0x3dcb

Mono: DllImport attempting to load: '__Internal'.Mono: Searching for 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResult'.Mono: Probing 'updateResultA'.Mono: Probing 'updateResultA'.Unable to resolve pinvoke method 'Math.MyClass:updateResult (int)' Re-run with MONO_LOG_LEVEL=debug for more information.

I've spent quite some time trying to figure this out. From what I've read it seems like this should be pretty trivial, but I can't get it to work. Any help would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

随遇而安 2024-10-26 03:35:03

使用选择器会更好吗?

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

Would it be better to use Selectors?

That is the default path to follow as suggested by the makers of MonoTouch.

情未る 2024-10-26 03:35:03

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

It could be a few things, but my first guess is that you aren't using the C symbol from anywhere in native code, and the DCE (dead code elimination) pass is removing it. Try disabling DCE in your Xcode project options.

不爱素颜 2024-10-26 03:35:03

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

I've had this problem myself, if you compare an objdump -T and objdump -t of your binary,
you'll find that the "D" flag is missing, so add a -rdynamic to your linker options.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文