社区
C#
帖子详情
C#调用C++:DLL的long类型参数“方法的类型签名与 PInvoke 不兼容错误”
fellowcheng
2005-01-17 03:25:33
如题
...全文
455
14
打赏
收藏
C#调用C++:DLL的long类型参数“方法的类型签名与 PInvoke 不兼容错误”
如题
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用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);
C#
异常原因解析
2、
C#
调
C++
写的
DLL
函数,出现“
方法
的
类型
签名
与P
Invoke
不兼容
错误
” 可能原因:
C#
与
C++
中对应
类型
长度不一致。 如:
C++
中一结构体定义为 struct A{ char buf[64]; }; 那么在
C#
中,若想在
DLL
函数中使用这个...
C#
调用
非托管
DLL
--[2]P
Invoke
签名
与非托管的目标
签名
不匹配
c#
调用
c++
非托管
DLL
调试报错 报错信息:
Invoke
调用
导致...关于
C#
调用
系统API 提示P
Invoke
签名
与非托管的目标
签名
不匹配。请检查 P
Invoke
签名
的
调用
约定和
参数
与非托管的目标
签名
是否匹配。这类问题解决方案。 ...
C#
调用
C++
dll
(
类型
对照)
原因可能是托管的 P
Invoke
签名
与非托管的目标
签名
不匹配。 在
dll
import中加入CallingConvention
参数
就行了,[
Dll
Import(PCAP_
DLL
, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] 要...
C#
调用
C++
dll
类型
对照表汇总
原因可能是托管的P
Invoke
签名
与非托管的目标
签名
不匹配,在
dll
import中加入CallingConvention
参数
就行了, [
Dll
Import(PCAP_
DLL
,CharSet=CharSet.Auto,CallingConvention=CallingConvention.Cdecl)] 要注意
C++
与...
C#
调用
C++
动态链接库
dll
C#
调用
C++
动态链接库
dll
由于公司很多底层的SDK,都是
C++
开发,上层的应用软件却是
C#
Winform程序。在实际工作的过程中,就经常碰到了
C#
程序
调用
C++
动态库的问题。最近一直在和
C++
打交道,
C#
怎么
调用
C++
类库...
C#
110,534
社区成员
642,576
社区内容
发帖
与我相关
我的任务
C#
.NET技术 C#
复制链接
扫一扫
分享
社区描述
.NET技术 C#
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
让您成为最强悍的C#开发者
试试用AI创作助手写篇文章吧
+ 用AI写文章