在linux中,mono调用我的.so-lib返回System.EntryPointNotFoundException
in linux, mono invoke my .so lib return System.EntryPointNotFoundException
这是我的c++代码
#include "_app_switcher.h"
std::string c_meth(std::string str_arg) {
return "prpr";
}
我的单声道代码:
[Test]
public void TestDraft()
{
Console.WriteLine(c_meth("prpr"));
}
[DllImport("/home/roroco/Dropbox/cs/App.Switcher/c/app-switcher/lib/libapp-switcher-t.so")]
private static extern string c_meth(string strArg);
错误输出:
System.EntryPointNotFoundException : c_meth
at (wrapper managed-to-native) Test.Ro.EnvTest.c_meth(string)
at Test.Ro.EnvTest.TestDraft () [0x00001] in /home/roroco/Dropbox/cs/Ro/TestRo/EnvTest.cs:15
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <71d8ad678db34313b7f718a414dfcb25>:0
我想这是因为我的头文件不在/usr/include中,那么如何在mono中指定c++头文件呢?
您的代码不起作用的原因有几个:
- 函数
c_meth
在共享库中不存在。确实存在的函数是_Z6c_methNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
- C++类
std::string
和.NET类System.String
是不同的,完全不相关。NET只知道如何将System.String
封送到const char*
,反之亦然
C++允许函数重载。这意味着它需要一种方法来区分void foo(int)
和void foo(std::string)
。为此,它使用名称篡改为每个重载生成一个唯一的名称。若要禁用函数的名称篡改,请使用extern "C"
说明符对其进行声明。这也将您限制为类C接口,因此您只能传递和返回基元对象和指针。没有类或引用。不过这很好,因为.NET不知道如何处理C++类。您需要接受一个原始const char*
参数并返回一个const char*
:
extern "C" const char* c_meth(const char* str_arg) {
return "prpr";
}
返回字符串也是有问题的。NET将在将字符串复制到托管堆后尝试取消分配返回的内存。由于在这种情况下返回的字符串没有使用适当的分配方法进行分配,因此这将失败。为了避免这种情况,您需要在C#中声明导入的方法以返回IntPtr
,并使用Marshal.PtrToString(Ansi|Unicode)
转换为System.String
。
如果您确实需要返回字符串常量以外的值,那么您有两个选项:
- 使用适当的函数为字符串分配内存。要使用的功能取决于平台。有关使用哪个函数的信息,请参阅Mono的文档
- 在C#中分配内存,并使用
System.Text.StringBuilder
将缓冲区传递给非托管函数:
C++侧:
extern "C" void c_meth(const char* str_arg, char* outbuf, int outsize) {
std::string ret = someFunctionThatReturnsAString(str_arg);
std::strncpy(outbuf, ret.c_str(), outsize);
}
C#侧:
[Test]
public void TestDraft()
{
StringBuilder sb = new StringBuilder(256)
c_meth("prpr", sb, 256);
Console.WriteLine(sb.ToString());
}
[DllImport("/home/roroco/Dropbox/cs/App.Switcher/c/app-switcher/lib/libapp-switcher-t.so")]
private static extern void c_meth(string strArg, StringBuilder outbuf, int outsize);
相关文章:
- 在linux中,mono调用我的.so-lib返回System.EntryPointNotFoundException
- /lib/libstdc++.so.6:没有可用的版本信息
- 链接器错误:在包含 .so lib 后未定义对 xxx 的引用
- 没有规则来设定目标'/usr/lib/x86_64-linux-gnu/libboost_filesystem.so'
- 使用 jna 加载 lib .so
- C++: 错误: opencv_core: 即使所需的 .so 文件位于 /usr/lib/ 中,也没有这样的文件或目录
- 我想从安卓工作室访问 .so lib 及其 cpp 文件的方法
- 如何在 C++ 中修复"/usr/bin/ld: warning: liblber-2.4.so.2, needed by //usr/lib/x86_64-linux-gnu/libcurl-gnu
- 从c#lib返回一个包含字符串到c 程序的结构
- 将 lib*.so 添加到 cmake
- 没有规则来使目标"TBB_ENV_LIB_DEBUG-NOTFOUND","lib/libopencv_core.so.3.2.0"需要
- collect2:错误:ld 在制作带有代码块的 .so 文件(64 位版本)时返回 1 个退出状态
- lib(libmyshlib.so,libmyshlib.so.1,libmyshlib.so.1.0)最好添加到我的项
- ./libmylib.so:未定义的"submarinex::LIB::kCount"
- 为什么我可以不将 SSL lib(-lssl) 链接到 so 的制作文件中?
- "/usr/lib/libstdc .so.6: version `GLIBCXX_3.4.15' not found"是什么意思,我该如何解决?
- 从.lib切换到.so后,Android应用程序崩溃
- "/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found`",如何解决?
- make[2]: *** 没有规则在 CGAL 中将目标 '/usr/lib/i386-linux-gnu/libmpfr.so'
- 编译 fortran 文件"/usr/bin/ld: errno: TLS definition in /lib/libc.so.6"