簡體   English   中英

在Linux中,單聲道調用我的.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 ++頭文件?

您的代碼無法正常工作的原因有兩個:

  1. 函數c_meth在共享庫中不存在。 確實存在的函數是_Z6c_methNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
  2. C ++類std::string和.NET類System.String是不同的,並且完全不相關。 .NET僅知道如何將System.Stringconst 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

如果確實需要返回字符串常量以外的其他值,則有兩種選擇:

  1. 使用適當的功能為字符串分配內存。 使用的功能取決於平台。 有關使用哪個功能的信息,請參見Mono的文檔
  2. 使用System.Text.StringBuilder在C#中分配內存,並將緩沖區傳遞給非托管函數:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM