我有一个C ++ DLL( SimpleDLL.dll ),带有一个具有函数指针( getNameFP )的公开函数( DllFunctionPoibnterGetName ) 。函数指针将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;
}
}
目前我可以设置长度没有任何问题,但我似乎找不到正确设置名称的方法。
我的问题是
答案 0 :(得分:1)
将char *转换为char []。这应该可以解决问题。
答案 1 :(得分:1)
投射char不会。 char *数据是“非托管”的本机数据。 C#使用'托管',.NET数据。
您需要为您的调用创建一个包装器,并使用marschall将数据从“非托管”转换为“托管”。
答案 2 :(得分: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
参数会更有意义。在输入时它会告诉你缓冲区有多大。在输出时,您将记录您复制到缓冲区的字节数。