我有一个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);
赞赏一些想法和建议。谢谢。
答案 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声明是准确的。您的实际代码不使用该声明,而是使用错误的声明。