从 C# GUI 将 char * 参数传递给 C++ dll 函数
Passing char * parameter to C++ dll function from C# GUI
我有一个 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[=12=]";
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);
一些想法和建议表示赞赏。谢谢。
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[=13=]";
System.Int16 Output = ReadPx(ref path, ref pix, ref num);
您添加的显式空终止符毫无意义。该框架确保编组的字符串具有空终止符。明确添加一个并没有什么坏处,但它没有任何用处。删除它。
更大的问题是如何传递字符串参数。代码说:
ref path
嗯,这不会编译,因为您的 p/invoke 将第一个参数声明为值参数,这确实应该如此。
很明显,问题中提供的信息是错误的。也许您的 p/invoke 声明错误地将第一个参数声明为 ref
参数,这与您的问题中所述相矛盾。
总而言之,根据我们掌握的信息,您在问题中提供的 p/invoke 声明是准确的。您的实际代码没有使用该声明,而是使用了错误的声明。
我有一个 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[=12=]";
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);
一些想法和建议表示赞赏。谢谢。
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[=13=]";
System.Int16 Output = ReadPx(ref path, ref pix, ref num);
您添加的显式空终止符毫无意义。该框架确保编组的字符串具有空终止符。明确添加一个并没有什么坏处,但它没有任何用处。删除它。
更大的问题是如何传递字符串参数。代码说:
ref path
嗯,这不会编译,因为您的 p/invoke 将第一个参数声明为值参数,这确实应该如此。
很明显,问题中提供的信息是错误的。也许您的 p/invoke 声明错误地将第一个参数声明为 ref
参数,这与您的问题中所述相矛盾。
总而言之,根据我们掌握的信息,您在问题中提供的 p/invoke 声明是准确的。您的实际代码没有使用该声明,而是使用了错误的声明。