C#调用C++DLL中 HANDLE *phCard怎么处理

coding008 2014-09-05 04:04:38
C++原函数声明是
DWORD _stdcall HSListReaders
(
OUT LPSTR pszReaderName,
IN OUT DWORD *pdwReaderNameLen,
OUT DWORD *pdwReaderNum
)
参数说明:
pszReaderName: 输出,多字符串,所有读写器的名称,如果该值为NULL, 由dwReaderNameLen返回读写器名字的长度。
pdwReaderNameLen: 返回读写器名字的长度。输入:缓冲区的长度,输出:读写器名称的长度。
pdwReaderNum: 输出,返回读写器的总个数。


DWORD _stdcall HSConnectDev
(
IN LPCSTR szDevName,
OUT HANDLE *phCard
)
参数说明:
szDevName: 输入,可用设备名。
phCard: 输出,设备的操作句柄。

[DllImport("GEA00001.dll", EntryPoint = "HSListReaders", CharSet = CharSet.Ansi)]
public static extern uint HSListReaders(System.Text.StringBuilder p, ref uint pdwReaderNameLen, ref uint pdwReaderNum);

[DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Auto)]
public static extern uint HSConnectDev(String szDevName, ref IntPtr hCard);

调用时这样的,设备名正常输出,但是获取设备的操作句柄,一直都是0,请大家帮忙

uint pdwReaderNum=0;
uint pdwReaderNameLen=0;
IntPtr hCard = IntPtr.Zero;

Class1.HSListReaders(null, ref pdwReaderNameLen, ref pdwReaderNum);

System.Text.StringBuilder pszReaderName = new System.Text.StringBuilder((int)pdwReaderNameLen);

Class1.HSListReaders(pszReaderName, ref pdwReaderNameLen, ref pdwReaderNum);


String szDevName = pszReaderName.ToString();

Class1.HSConnectDev(szDevName, ref hCard);
...全文
315 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2014-09-12
  • 打赏
  • 举报
回复
一般这样传输都是基于 REG_MULTI_SZ 的 BSTR。 也就是说,是以 NULL 为结尾的 字符串数组,最后以两个 NULL 为结尾的 BSTR 字符串。 你可以获取缓冲区后,自己枚举字符串数组。
		private IEnumerable<string> PtrToStringBSTR(IntPtr ptr)
		{
			while (Marshal.ReadInt16(ptr) != 0)
			{
				string str = Marshal.PtrToStringUni(ptr);
				ptr += (str.Length + 1) * 2;
				yield return str;
			}
		}
			private static extern int _GetBufferedMBSTR([In] IntPtr @this, [In, MarshalAs(UnmanagedType.I4)] int index, [In, Out] IntPtr buffer, [In] int size, [Out] out int length);
	public string[] GetBufferedString(int index)
		{
			IntPtr buffer = Marshal.AllocCoTaskMem(256 * 2);
			int length = 0;
			try
			{
				_GetBufferedMBSTR(_basecpp, index, buffer, 256, out length);
				return PtrToStringBSTR(buffer).ToArray();
			}
			finally
			{
				Marshal.FreeCoTaskMem(buffer);
			}
		}
mjp1234airen4385 2014-09-12
  • 打赏
  • 举报
回复
byte[] bytes = new byte[145]; Marshal.Copy(buffer, bytes, 0, 145); 再把bytes按照'\0'分组,分别转换成string
mjp1234airen4385 2014-09-12
  • 打赏
  • 举报
回复
那就不能使用StringBuilder做为参数了,你试试IntPtr,并且分配145个长度,再传入。 public static extern uint HSListReaders(IntPtr p,。。。。 IntPtr buffer = Marshal.AllocHGlobal(145); HSListReaders(buffer,...
mjp1234airen4385 2014-09-11
  • 打赏
  • 举报
回复
难道是华视读卡器? [DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Auto)] 改成Ansi。 另外如果读卡器没有问题的话,你看看读到的设备名称是不是正确,末尾是不是有不可显示的字符什么的。 再试试StringBuilder的编码格式,也许不正确。
coding008 2014-09-11
  • 打赏
  • 举报
回复
引用 8 楼 Forty2 的回复:
先检查返回的pdwReaderNum是否为1, 如果是零,可能有错误, 如果大于一,返回字符串可能是多字符串。
是多字符串,那应该用什么接受呢,stringbuffer,不行
Forty2 2014-09-11
  • 打赏
  • 举报
回复
可以传如用byte[] p。解码可以:

void Test()
{
    string multiString = "hello" + (char)0 + "world" + (char)0 + (char)0;
    byte[] bytes = Encoding.Default.GetBytes(multiString);
    List<string> strs = GetMultiString(bytes);
}

static List<string> GetMultiString(byte[] bytes)
{
    List<string> result = new List<string>();
    for (int i = 0; i < bytes.Length; )
    {
        int j = Array.IndexOf<byte>(bytes, 0, i);
        if (j == -1 || j - i < 2) break;
        result.Add(Encoding.Default.GetString(bytes, i, j - i));
        i = j + 1;
    }
    return result;
}
coding008 2014-09-11
  • 打赏
  • 举报
回复
引用 10 楼 mjp1234airen4385 的回复:
难道是华视读卡器? [DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Auto)] 改成Ansi。 另外如果读卡器没有问题的话,你看看读到的设备名称是不是正确,末尾是不是有不可显示的字符什么的。 再试试StringBuilder的编码格式,也许不正确。
现在发现问题的在哪儿了,求各位帮忙解决 编码改为Ansi,是可以,但是返回的LPSTR 中有“/0”,在转入到StringBuilder遇到“/0”之后就结束,不再继续把值传入到StringBuilder中,一共有八个值,只能取到第一个 如果使用Unicode或者Auto,等到的值又是乱码,求大家帮忙
coding008 2014-09-11
  • 打赏
  • 举报
回复
引用 10 楼 mjp1234airen4385 的回复:
难道是华视读卡器? [DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Auto)] 改成Ansi。 另外如果读卡器没有问题的话,你看看读到的设备名称是不是正确,末尾是不是有不可显示的字符什么的。 再试试StringBuilder的编码格式,也许不正确。
不是华数的,是海泰的,C++中返回的char*是145但是StringBuilder只返回了第一个char*数组,怎么处理
Forty2 2014-09-05
  • 打赏
  • 举报
回复
先检查返回的pdwReaderNum是否为1, 如果是零,可能有错误, 如果大于一,返回字符串可能是多字符串。
coding008 2014-09-05
  • 打赏
  • 举报
回复
还是不行,第一个函数的需要修改吗
引用 2 楼 Saleayas 的回复:
所有 C++ 的 OUT 参数,C# 需要使用 [Out] 特性.
coding008 2014-09-05
  • 打赏
  • 举报
回复
还是不行,第一个函数的需要修改吗
引用 1 楼 Forty2 的回复:
DllImport("GEA00001.dll", EntryPoint = "HSListReaders", CharSet = CharSet.Ansi)] public static extern uint HSListReaders(System.Text.StringBuilder p, ref uint pdwReaderNameLen, ref uint pdwReaderNum); [DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Ansi)] public static extern uint HSConnectDev(String szDevName, ref IntPtr hCard); 一出一进编码要一样。
Saleayas 2014-09-05
  • 打赏
  • 举报
回复
[DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Auto)] public static extern uint HSConnectDev(String szDevName, [Out] out IntPtr hCard);
coding008 2014-09-05
  • 打赏
  • 举报
回复
引用 2 楼 Saleayas 的回复:
所有 C++ 的 OUT 参数,C# 需要使用 [Out] 特性.
能具体点吗?
coding008 2014-09-05
  • 打赏
  • 举报
回复
编码修改了,解决一部分问题,但是设备句柄还未0
Saleayas 2014-09-05
  • 打赏
  • 举报
回复
所有 C++ 的 OUT 参数,C# 需要使用 [Out] 特性.
Forty2 2014-09-05
  • 打赏
  • 举报
回复
DllImport("GEA00001.dll", EntryPoint = "HSListReaders", CharSet = CharSet.Ansi)] public static extern uint HSListReaders(System.Text.StringBuilder p, ref uint pdwReaderNameLen, ref uint pdwReaderNum); [DllImport("GEA00001.dll", EntryPoint = "HSConnectDev", CharSet = CharSet.Ansi)] public static extern uint HSConnectDev(String szDevName, ref IntPtr hCard); 一出一进编码要一样。

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧