将char *参数从C#GUI传递给C ++ dll函数

时间:2017-06-20 18:28:21

标签: c# c++ pointers dll dllimport

我有一个cpp函数作为DLL文件从某个文件路径读取文件并返回" 0"如果成功和其他数字如果失败了:

short __stdcall ReadPx(char *filePath, MAP *map, int *num);

此功能在我的C#中定义为:

[DllImport("lib.dll", EntryPoint = "ReadPx", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern System.Int16 ReadPx([MarshalAs(UnmanagedType.LPStr)] string filePath, ref MAP Map, ref Int32 numE);

它在主函数中被称为:

var pix = new MAP();
int num = 1;
string path = "C:/Users/Visual Studio 2015/Projects/testWrapper2/Map\0";
System.Int16 Output = ReadPx(path, ref pix, ref num);
Console.WriteLine(Output);

该函数运行正常,但文件路径错误无效。我认为问题可能是在C#代码中将“String filePath”定义为Unicode(每个字符2个字节),而ReadPx需要指向简单ASCII字符串的指针。这就是为什么我尝试了下面显示的一些修改,但文件路径错误仍然存​​在。

[DllImport("lib.dll", EntryPoint = "ReadPx", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern System.Int16 ScReadPixMap(IntPtr filePath, ref PIXMAPENTRY pixMap, ref Int32 numEntries);

IntPtr ptrCString = (IntPtr)Marshal.StringToHGlobalAnsi(path);
System.Int16 output = ReadPx(ptrCString, ref pix, ref num);
Marshal.FreeHGlobal(ptrCString);

赞赏一些想法和建议。谢谢。

1 个答案:

答案 0 :(得分:0)

C ++声明是:

short __stdcall ReadPx(char *filePath, MAP *map, int *num);

您的C#声明是:

[DllImport("lib.dll", EntryPoint = "ReadPx", 
    CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern System.Int16 ReadPx(
    [MarshalAs(UnmanagedType.LPStr)] string filePath, 
    ref MAP Map, 
    ref Int32 numE
);

鉴于我们提供的信息,这里没有错误。但请注意,我们不知道如何声明MAP,并且可能存在错误。我认为,第二个和第三个参数可能是数组。只有你能知道这些细节。

p / invoke声明比必要的更冗长。是我,我会这样写:

[DllImport("lib.dll")]
public static extern short ReadPx(string filePath, ref MAP Map, ref int numE);

在你的问题中,你继续声明你这样称呼函数:

string path = "C:/Users/Visual Studio 2015/Projects/testWrapper2/Map\0";
System.Int16 Output = ReadPx(ref path, ref pix, ref num);

您添加的显式空终止符是没有意义的。该框架确保编组的字符串具有空终止符。明确添加一个并不会有害,但它没有用处。删除它。

更大的问题是如何传递字符串参数。代码说:

ref path

那么,这将无法编译,因为你的p / invoke将第一个参数声明为值参数,就像它应该的那样。

显然,问题中提供的信息是错误的。也许你的p / invoke声明错误地将第一个参数声明为ref参数,这与你的问题中陈述的内容相矛盾。

总之,根据我们提供的信息,您在问题中提供的p / invoke声明是准确的。您的实际代码不使用该声明,而是使用错误的声明。