简体   繁体   English

在Linux中,单声道调用我的.so lib返回System.EntryPointNotFoundException

[英]in linux, mono invoke my .so lib return System.EntryPointNotFoundException

here is my c++ code 这是我的C ++代码

#include "_app_switcher.h"

std::string c_meth(std::string str_arg) {
    return "prpr";
}

my mono code: 我的单声道代码:

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

the err output: 错误输出:

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

I guess it's because my header file is not in /usr/include, so how to specific c++ header file in mono? 我猜这是因为我的头文件不在/ usr / include中,所以如何在mono中指定c ++头文件?

There are a couple of reasons why your code doesn't work: 您的代码无法正常工作的原因有两个:

  1. The function c_meth does not exist within your shared library. 函数c_meth在共享库中不存在。 The function that does exist is _Z6c_methNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE . 确实存在的函数是_Z6c_methNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
  2. The C++ class std::string and the .NET class System.String are different and entirely unrelated. C ++类std::string和.NET类System.String是不同的,并且完全不相关。 .NET only knows how to marshal System.String to const char* and vice versa. .NET仅知道如何将System.Stringconst char* ,反之亦然。

C++ allows function overloading. C ++允许函数重载。 That means it needs a way to tell void foo(int) apart from void foo(std::string) . 这意味着它需要一种方法来区分void foo(int)void foo(std::string) To do this, it uses name mangling to generate a unique name for each overload. 为此,它使用名称修饰为每个重载生成唯一的名称。 To disable name mangling for a function you declare it with the extern "C" specifier. 要禁用功能的名称修饰,请使用extern "C"说明符对其进行声明。 This also limits you to C-like interfaces, so you can only pass and return primitive objects and pointers. 这也将您限制为类似C的接口,因此您只能传递和返回原始对象和指针。 No classes or references. 没有类别或参考。 That's fine though, since .NET doesn't know what to do with C++ classes. 不过,这很好,因为.NET不知道如何处理C ++类。 You need to accept a raw const char* parameter and return a const char* : 您需要接受一个原始的const char*参数并返回一个const char*

extern "C" const char* c_meth(const char* str_arg) {
    return "prpr";
}

Returning strings is also problematic. 返回字符串也是有问题的。 .NET will try to de-allocate the returned memory after copying the string to the managed heap. 将字符串复制到托管堆后,.NET将尝试取消分配返回的内存。 Since the string returned in this case wasn't allocated using the appropriate allocation method, that will fail. 由于在这种情况下返回的字符串未使用适当的分配方法进行分配,因此将失败。 To avoid this you'll need to declare the imported method in C# to return an IntPtr and use Marshal.PtrToString(Ansi|Unicode) to convert to a System.String . 为避免这种情况,您需要在C#中声明导入的方法以返回IntPtr并使用Marshal.PtrToString(Ansi|Unicode)转换为System.String

If you do need to return something other than a string constant, you have a couple options: 如果确实需要返回字符串常量以外的其他值,则有两种选择:

  1. Allocate the memory for the string with the appropriate function. 使用适当的功能为字符串分配内存。 The function to use is platform-dependent. 使用的功能取决于平台。 See Mono's documentation for info about which function to use. 有关使用哪个功能的信息,请参见Mono的文档
  2. Allocate the memory in C# and pass the buffer to the unmanaged function using a System.Text.StringBuilder : 使用System.Text.StringBuilder在C#中分配内存,并将缓冲区传递给非托管函数:

C++ side: 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# side: 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Mono 2.8上的SWIG中的System.EntryPointNotFoundException错误 - System.EntryPointNotFoundException error in SWIG on mono 2.8 为什么我总是在 mscor.lib 中得到“System.EntryPointNotFoundException”? - Why do I always get a “System.EntryPointNotFoundException” in mscor.lib? System.EntryPointNotFoundException以平行红色显示在输出中 - System.EntryPointNotFoundException in Parallel red in output System.EntryPointNotFoundException:无法找到入口点 - System.EntryPointNotFoundException: Unable to find an entry point 未处理的异常:DLL中的System.EntryPointNotFoundException - Unhandled Exception: System.EntryPointNotFoundException in DLL 使用aff文件时System.EntryPointNotFoundException - System.EntryPointNotFoundException when using aff file System.EntryPointNotFoundException和DllImport(“ kernel32.dll”) - System.EntryPointNotFoundException and DllImport(“kernel32.dll”) 从 DLL 调用 function 时出现 System.EntryPointNotFoundException - System.EntryPointNotFoundException when calling function from DLL Owin / Katana System.EntryPointNotFoundException程序集位于其他位置 - Owin/Katana System.EntryPointNotFoundException Assembly located elsewhere 无法使用Magick.NET:System.EntryPointNotFoundException - Can't use Magick.NET: System.EntryPointNotFoundException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM