簡體   English   中英

使用包含來自C#的char *的回調函數調用C ++ DLL

[英]Calling C++ DLL with a callback function that contains a char* from C#

我有一個C ++ DLL(SimpleDLL.dll),具有暴露的功能(DllFunctionPoibnterGetName),其具有一個函數指針(getNameFP)。 函數指針將char *作為參數(* char * name *)。

// C++ 
DllExport void DllFunctionPoibnterGetName( void (*getNameFP) (char * name, unsigned short * length ) ) {

    char name[1024];
    unsigned short length = 0 ; 
    getNameFP( name, &length ); 

    printf( "length=[%d] name=[%s]\n", length, name ); 
}

我有一個想要使用這個C ++ DLL的C#應用​​程序。

// C# 
public unsafe delegate void GetName( System.Char* name, System.UInt16* length); 
unsafe class Program
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void delegateGetName(System.Char* name, System.UInt16* length);

    [DllImport("SimpleDLL.dll", CharSet = CharSet.Ansi )]
    public static extern void DllFunctionPoibnterGetName([MarshalAs(UnmanagedType.FunctionPtr)] delegateGetName getName);

    static void Main(string[] args)
    {   
        DllFunctionPoibnterGetName(GetName); 
    }

    static void GetName(System.Char* name, System.UInt16* length)
    {
        // name = "one two three";
        *length = 10; 
    }   
}

目前我可以設置長度沒有任何問題,但我似乎無法找到正確設置名稱的方法。

我的問題是

  • 如何正確地將char *名稱設置為值。

將char *轉換為char []。 這應該夠了吧。

鑄造char不會。 char *數據是“非托管”的本機數據。 C#使用'托管',.NET數據。

您需要為調用創建一個包裝器並使用marschall將數據從“非托管”轉換為“托管”。

您不需要使用不安全的代碼。 你可以這樣做:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void delegateGetName(IntPtr name, out ushort length);
....
static void GetName(IntPtr name, out ushort length)
{
    byte[] buffer = Encoding.Default.GetBytes("one two three");
    length = (ushort)buffer.Length;
    Marshal.Copy(buffer, 0, name, buffer.Length);
}   

雖然這種界面設計只是要求緩沖區溢出。 你怎么知道非托管緩沖區有多大? 通過ref傳遞length參數會更有意義。 在輸入時它會告訴你緩沖區有多大。 在輸出時,您將記錄您復制到緩沖區的字節數。

暫無
暫無

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

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