1

我有一个 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 *名称设置为一个值。
4

3 回答 3

1

你不需要使用不安全的代码。你可以这样做:

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

虽然这个接口设计只是要求缓冲区溢出。你怎么知道非托管缓冲区有多大?length传递参数会更有意义ref。在输入时它会告诉你缓冲区有多大。在输出时,您会记录复制到缓冲区中的字节数。

于 2012-11-09T18:46:24.710 回答
1

铸造 char 是不行的。char * 数据是“非托管”的本机数据。而 C# 使用“托管”的 .NET 数据。

您需要为您的调用制作一个包装器,并使用 marschall 将数据从“非托管”转换为“托管”。

于 2012-11-09T18:39:11.643 回答
1

将 char* 转换为 char[]。这应该够了吧。

于 2012-11-09T18:12:58.187 回答