在 ubuntu 操作系统中从单声道 P/Invoke g++
Posted
技术标签:
【中文标题】在 ubuntu 操作系统中从单声道 P/Invoke g++【英文标题】:P/Invoke g++ from mono in ubuntu OS 【发布时间】:2011-05-05 17:22:11 【问题描述】:是否可以在 Ubuntu 中从 mono 调用 g++ 可执行文件的函数?请注意,在 Ubuntu 操作系统中编译的 C++ 和 C# 代码。
C++应用源码:
#include <stdlib.h>
static int32_t Sum(int32_t a, int32_t b)
return a + b;
/*
*
*/
int main(int argc, char** argv)
return (EXIT_SUCCESS);
C#单声道应用源码:
using System;
using System.Runtime.InteropServices;
namespace MonoCsTest
class MainClass
[DllImport("/home/.../MonoCsTest/bin/Debug/testcpp")]
public static extern Int32 Sum(Int32 a, Int32 b);
public static void Main (string[] args)
Console.WriteLine (" 5 + 6 = " + Sum(5,6));
这会抛出DllNotFoundException
【问题讨论】:
我有一个共享库 (.so) here 的示例。这有帮助吗? 感谢那个 dtb,但我的问题是DllNotFoundException
!!!我确定文件路径是正确的!我想这一定是一个愚蠢的问题! :)
【参考方案1】:
您需要将库编译为共享库:静态库不能在运行时使用 P/Invoke 加载。 您添加了 main() 函数的事实表明您正在将代码编译为可执行文件。 所以你首先要学习如何编译一个共享库,你可以试试这样的:
gcc -shared -o libtestcpp.so testcpp.cpp
然后将DllImport名称改为完整库名的路径:
DllImport("/home/yourlogin/MonoCsTest/bin/Debug/libtestcpp.so")
您犯的另一个错误是没有考虑 C++ 强制名称修改:这里更简单的解决方案是将 Sum() 导出为使用 extern "C"
包围它的 C 函数。
要诊断此类错误,通常可以使用以下命令从单声道启用调试日志记录:
MONO_LOG_LEVEL="debug" MONO_LOG_MASK="dll" mono yourprog.exe
【讨论】:
名称修改通常会导致 EntryPointNotFound 异常,而不是 DllNotFound。据我所知,Mono 可以使用从可执行文件和共享库中导出的符号(不过我对此并不完全确定)。 我当然知道异常类型(fwiw,我实现了 mono 的这一部分),这就是为什么我首先向他指出他得到 DllNotFound 异常的原因,后来我指出了另一个一旦他解决了第一个问题,他就会遇到。至于您不确定的部分:您的句子不正确。当使用特殊的 DllImport 名称“__Internal”时,Mono 可以从(正确链接的)共享库中加载导出的符号,并从嵌入 mono 的 进程(注意,不可执行)中加载全局导出的符号。有一个半例外:PIE 可执行文件。 但是 PIE 可执行文件基本上是共享库,我不想把它们拿出来,因为人们已经很困惑了:)【参考方案2】:只要导出一个符号并且 Mono 可以理解参数(足以将数据编组到/来自它们),那么是的,您可以这样做。我认为 PInvoke 上的 Mono 页面实际上提到您可以调用由库和可执行文件导出的函数,包括嵌入 Mono 的可执行文件。
您需要验证该符号确实被导出,更重要的是,它没有被破坏或者您在 C# 端匹配它。那是我遇到过最愚蠢问题的地方。
【讨论】:
问题是DllNotFoundException
!是因为数据类型不匹配吗?我不认为! :)
从错误中,我猜它只是找不到库(或者这是最好的起点)。你检查过路径,确保名称是正确的吗?
是的,我检查了!我还检查文件权限。 :'(
尝试将 C++ 库或可执行文件与 Mono 可执行文件放在同一目录中,并将其作为工作目录运行。这个页面或许能提供更多帮助,是 Mono 的互操作信息:mono-project.com/Interop_with_Native_Libraries以上是关于在 ubuntu 操作系统中从单声道 P/Invoke g++的主要内容,如果未能解决你的问题,请参考以下文章