C#调用C++:DLL的long类型参数“方法的类型签名与 PInvoke 不兼容错误”

fellowcheng 2005-01-17 03:25:33
如题
...全文
455 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
fellowcheng 2005-01-20
  • 打赏
  • 举报
回复
算了,用VB6做吧

虽然没有解决,但还是非常感谢YvesGao(叶辉)的热心帮助
fellowcheng 2005-01-19
  • 打赏
  • 举报
回复
再顶一下
YvesGao 2005-01-19
  • 打赏
  • 举报
回复
我利用你的那个dll自己做了一个C#的sln
果然出错,是那个方法的类型签名与 PInvoke 不兼容错误
我仔细一看才发现 原来 DeviceInfo 返回的是一个结构体 而不是一个结构体指针
我研究P/Invoke是用来调用win32api,win32api中传递的都是结构体指针,至少我所看的这些资料上是这样的,这种 返回值的类型 是结构体(它代表一块非托管内存)的情况我从未遇见过,我在msdn上查到的资料,也没说如何处理这种情况,我也感到很困惑,为什么不能封送处理一整块内存。
我研究了一早晨也没想到办法,我想可能要问问别的做过这方面研究的朋友了,
我猜想也许需要自定义封送处理?
我也想到一个变通的方法,供你参考,你可以写一个dll,这个dll导出一个DeviceInfoWrapper函数,它提供一个传出参数 是 指向devinfo的结构体指针,这个函数内部再调用Prr803xLib.dll的DeviceInfo。我的意思就是在非托管代码中将DevInfo结构转换成指针再传递给P/Invoke。
除此之外,我实在没招了,:(
我在写一个关于P/Invoke 的论文,看来你给我找了点可以写的东西,如果我研究明白的话,呵呵
YvesGao 2005-01-19
  • 打赏
  • 举报
回复
下午,又去查了MSDN,确切地找到了这个主题,但是没有解决方法,有很多关于结构体作为参数传递的情况及解决方法(11种之多),但就是没有结构体作为返回值的情况,非常诧异,难道是微软疏漏了?
我看你写个wrapper吧
fellowcheng 2005-01-19
  • 打赏
  • 举报
回复
还有没有人help
mm521 2005-01-18
  • 打赏
  • 举报
回复
c#的long是64位吧
快速开始中有些例子
fellowcheng 2005-01-18
  • 打赏
  • 举报
回复
up
YvesGao 2005-01-18
  • 打赏
  • 举报
回复
出的什么错,错误信息是什么?
如果方便的话,把这个C#的解决方案,就这个最小的就可以,能说明问题就可以了,发给我
fellowcheng 2005-01-18
  • 打赏
  • 举报
回复
函数原型:

#ifndef _GLOBALS_H_
#define _GLOBALS_H_

#define DllImport __declspec(dllimport)

struct DetectLableMode
{
char *DetectLable;
int LableNum;
}strDetectLableMode;

struct DevInfo
{
char Sw_Rev[50];
char D_Rev[50];
char Hw_Type[50];
char Sw_Type[50];
char Tr_Type[50];
} strDevInfo;

extern "C" DllImport HANDLE __stdcall OpenCom(int nPort,long nBaudRate,
int nParity,
int nDataBits,int nStopBit,
int nFlowCtl);

extern "C" DllImport void __stdcall CloseCom(HANDLE hComm);

extern "C" DllImport char* __stdcall SetAntenna(HANDLE hComm,BYTE Addr, BOOL bStats);

extern "C" DllImport DetectLableMode __stdcall DetectTagUID(HANDLE hComm,BYTE Addr,
BOOL Tag = 0);

extern "C" DllImport BOOL __stdcall ReadTagData(HANDLE hComm,
BYTE Addr, BYTE Mode,BYTE *UID,
BYTE BlockAddr,BYTE nBlockNum,
char *ReadData);

extern "C" DllImport DevInfo __stdcall DeviceInfo(HANDLE hComm, BYTE Addr);
extern "C" DllImport BOOL __stdcall DetectBaud(HANDLE hComm,BYTE Addr);

extern "C" DllImport char* __stdcall GetSysInfo(HANDLE hComm,
BYTE Addr, BYTE Mode, BYTE *UID);
extern "C" DllImport BOOL __stdcall WriteTagAFI(HANDLE hComm, BYTE Addr, BYTE Mode,
BYTE *UID, BYTE NewAFI);
extern "C" DllImport BOOL __stdcall LockTagAFI(HANDLE hComm, BYTE Addr, BYTE Mode,
BYTE *UID);

extern "C" DllImport BOOL __stdcall WriteTagDSFID(HANDLE hComm, BYTE Addr, BYTE Mode,
BYTE *UID, BYTE NewDSFID);
extern "C" DllImport BOOL __stdcall LockTagDSFID(HANDLE hComm, BYTE Addr, BYTE Mode,
BYTE *UID);

extern "C" DllImport BOOL __stdcall WriteSingleBlock(HANDLE hComm,
BYTE Addr, BYTE Mode,BYTE *UID,BYTE BlockAddr,
BYTE *WriteData);
extern "C" DllImport BOOL __stdcall CheckSingleTagBlockStatus(
HANDLE hComm,BYTE Addr, BYTE Mode,
BYTE *UID, BYTE BlockAddr,
int nBlockNum,char *Stats);
extern "C" DllImport char* __stdcall LockTagBlocks(HANDLE hComm, BYTE Addr, BYTE Mode,
BYTE BeginBlock, BYTE Blocks, BYTE *UID);

#endif
fellowcheng 2005-01-18
  • 打赏
  • 举报
回复
先谢谢YvesGao(叶辉)的热心帮助!!
不过还没成功呀!
[DllImport("Prr803xLib.dll",EntryPoint= "OpenCom")]
public static extern IntPtr OpenCom(Int32 nPort,Int32 nBaudRate,Int32 nParity,Int32 nDataBits,Int32 nStopBit,Int32 nFlowCtl);

[DllImport("Prr803xLib.dll",EntryPoint="CloseCom")]
public static extern void CloseCom(Int32 nPort);

[DllImport("Prr803xLib.dll",EntryPoint = "DeviceInfo")]
public static extern DevInfo DeviceInfo(IntPtr hCom,Byte Addr);

public struct DevInfo
{
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Sw_Rev;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string D_Rev;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Hw_Type;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Sw_Type;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Tr_Type;
}
调用代码如下:
private void btOpenPort_Click(object sender, System.EventArgs e)
{
try
{
IntPtr hCom= OpenCom(2,9600, 2, 8, 0, 0);

m_DevInfo = DeviceInfo(hCom,0); //这里出错!!
this.txtDeviceInfo.Text+="\n"+m_DevInfo.Sw_Rev;

}
catch(Exception ept)
{
this.txtDeviceInfo.Text+="\n"+ept.Message;
}
finally
{
CloseCom(2);

}
}
YvesGao 2005-01-18
  • 打赏
  • 举报
回复
我看了DeviceInfo 的函数原型为:
extern "C" DllImport DevInfo __stdcall DeviceInfo(HANDLE hComm, BYTE Addr);
所以应是你在C#中的映射原型写错了,应为:
[DllImport("Prr803xLib.dll" ,EntryPoint = "DeviceInfo")]
public static extern DevInfo DeviceInfo(System.IntPtr hComm, byte Addr);
HANDLE 的类型为void* 对应于托管的System.IntPtr
另外,DevInfo结构的原型为:
struct DevInfo
{
char Sw_Rev[50];
char D_Rev[50];
char Hw_Type[50];
char Sw_Type[50];
char Tr_Type[50];
} strDevInfo;
在C#中的映射类型为:
struct DevInfo
{
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Sw_Rev;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string D_Rev;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Hw_Type;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Sw_Type;
[MarshalAs(UnmanagedType.ByValTStr , SizeConst = 50)]
public string Tr_Type;
}
这些都属于一类P/Invoke问题,如果不是很清楚的话,可以先花一点时间,查看相关资料,然后就迎刃而解了,推荐一篇文章,相信能够帮到你,原始出处是MSDN magazine
http://blog.csdn.net/web_gus/archive/2004/10/26/152622.aspx

另外,下面这个帖子上也有一些相关资料,可以供进一步学习之用

http://community.csdn.net/Expert/topic/3708/3708210.xml?temp=.963772


YvesGao 2005-01-17
  • 打赏
  • 举报
回复
Prr803xLib.dll
中的函数原型是什么?有没有c的声明?
在VB5中Long是32位的么?
解决这类问题,关键在于跟踪数据在托管和非托管代码中的表示形式,
我也在研究P/Invoke方面的一些问题,不如提供多一些的信息,我来看看。
fellowcheng 2005-01-17
  • 打赏
  • 举报
回复
up
fellowcheng 2005-01-17
  • 打赏
  • 举报
回复
VB5.0:
Public Declare Function DeviceInfo Lib "Prr803xLib.dll" (ByVal hCom As Long, ByVal Addr As Byte) As DevInfo

C#中:
[DllImport("Prr803xLib.dll")]
public static extern DevInfo DeviceInfo(int hCom,byte Addr);

110,534

社区成员

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

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

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