从C#应用程序调用C ++ DLL方法

时间:2012-01-30 10:38:07

标签: c# c++ .net dll

我正在尝试在C#项目中使用C ++ DLL中的方法,但是我在调​​用它时遇到了问题。 方法是这样的:

如SDK手册中所述

<击>     DWORD WINAPI PrtRead(HANDLE hPrt,DWORD dwTimeout,DWORD * pdwType,LPDWORD pdwParArray,LPDWORD pdwArraySize,LPBYTE pbReadData,LPDWORD pdwReadDataLen)

正如在代码上真正定义的那样

extern "C" __declspec(dllimport) DWORD PrtRead (HANDLE hPRT, DWORD dwTimeout, DWORD *pdwType, LPDWORD pdwParArray, LPDWORD pdwArraySize,LPBYTE  pbReadData, LPDWORD pdwReadDataLen);

在SDK C ++示例中,他们将其称为:

DWORD       dwPar[2];
pdwParArray = &dwPar[0];
dwPar[0] = 0;
dwPar[1] = 0;

DWORD dwRet = PrtRead(hPrinter, dwCurrentTimeout, &dwType, pdwParArray, &dwArraySize, NULL, &dwReadDataLen);

我的问题是获取值LPDWORD pdwParArray。

DLL总是返回位置[0]中的以下值之一:1,2或20并且位置[1]:1,2或4,但我没有让它做到这一点。

我尝试像这样定义导入:

[DllImport("HPRDH.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong PrtRead(IntPtr hPrt, ulong dwTimeout, ref ulong pdwType, XXXXXXXXX , ref ulong pdwArraySize, ref byte[] pbReadData, ref ulong pdwReadDataLen);

并且像这样改变XXXXXXXXX


方法定义:

out ulong[] pdwParArray

变量初始化:

ulong[] pdwParArray;

方法返回:

pdwParArray = null

方法定义:

ref ulong[] pdwParArray

变量初始化:

ulong[] pdwParArray = new ulong[2];
pdwParArray[0] = 0;
pdwParArray[1] = 0;

方法返回:     pdwParArray [0] = 0;     pdwParArray [1] =超出范围的数组索引;


方法定义:     out ulong pdwParArray

变量初始化:     ulong [] pdwParArray = new ulong [2];

方法返回:     pdwParArray [0] = 0;     pdwParArray [1] = 0;


方法定义:     ref ulong pdwParArray

变量初始化:     ulong [] pdwParArray = new ulong [2];

方法返回:     pdwParArray [0] = 0;     pdwParArray [1] = 0;


如何在C#import中定义LPDWORD pdwParArray,如何初始化并调用它?

提前致谢

_
_
_
_

修改 @TheMathemagician

尝试以下结果:

定义:

[MarshalAs(UnManagedType.LPArray)] ulong [] pdwParArray

结果:

pdwParArray [0] = 0;

pdwParArray [1] = 0;


定义:

[MarshalAs(UnmanagedType.LPArray)] out ulong [] pdwParArray

结果:

pdwParArray [0] = null;

pdwParArray [1] = null;


定义:

[MarshalAs(UnmanagedType.LPArray)] ulong pdwParArray

结果:

无法编组'参数#4':无效的托管/非托管类型组合(Int64 / UInt64必须与I8或U8配对)。


定义:

[MarshalAs(UnmaDefinition:nagedType.LPArray)] out ulong pdwParArray

结果:

无法编组'参数#4':无效的托管/非托管类型组合(Int64 / UInt64必须与I8或U8配对)。

5 个答案:

答案 0 :(得分:1)

你说的方法是WINAPI调用,而不是cdecl 在您的c#应用程序中,您将其声明为cdecl

答案 1 :(得分:0)

尝试将其声明为[MarshalAs(UnManagedType.LPArray)] ulong [] pdwParArray

在C#中确定ulong是一个64位整数(在Windows 7上),我发现如果我将所有的ulong更改为Int32,它对我使用相同签名构建的DLL函数起作用。

所以我有: [DllImport(“SPLibNet.dll”,CallingConvention = CallingConvention.StdCall)] public static extern Int32 PrtRead(IntPtr hPtr,Int32 dwTimeout,ref Int32 pdwType, [MarshalAs(UnmanagedType.LPArray)] Int32 [] pdwParArray,...

我的DLL能够在pdwParArray中设置值

答案 2 :(得分:0)

我注意到的一件事是你为导入的函数指定了错误的CallingConvention。

在C ++中,WINAPI被定义为

#define WINAPI __stdcall

所以你的C#导入应该是

[DllImport("HPRDH.dll", CallingConvention = CallingConvention.StdCall)]
public static extern ulong PrtRead(IntPtr hPrt, ulong dwTimeout, ref ulong pdwType, XXXXXXXXX , ref ulong pdwArraySize, ref byte[] pbReadData, ref ulong pdwReadDataLen);

答案 3 :(得分:0)

使用此处的表格进行转换,并更正调用约定: Pinvoke.net

答案 4 :(得分:0)

由于几乎所有的答案都是关于同一件事,即使如此也没有用,我决定更深入地研究SDK示例,并意识到我需要第二次调用PrtRead(...)得到正确的价值。

我最终使用:

[DllImport("HPRDH.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 PrtRead(IntPtr hPrt, UInt32 dwTimeout, ref UInt32 pdwType, out UInt32 pdwParArray, ref UInt32 pdwArraySize, ref byte[] pbReadData, ref UInt32 pdwReadDataLen);