C++ 数据类型与C#中的对应关系

紫舞玥汐 2012-06-15 04:58:59
最近做的项目,要在C#中调用C++写的dll
但是无论怎么写总是有“对 PInvoke 函数的调用导致堆栈不对称。原因可能是托管的 PInvoke..."这样的爆报错。查了下可能是数据类型的问题,网上的搜到过很多这种对照表,但是我这个函数中有几个数据类型不在这些对照表中,试过网上说的 几种,到最后还是有问题。所以请大家帮我看一下,到底是什么问题。

C++: const char *pszBuffer,DWORD dwSize,chsr **pszOutPut,DWORD *pdwRecv

在C#中我用过以下几种:
string sendStr, int sendSize, string[] recvStr, int recvSize
string sendStr, int sendSize, ref string recvStr, ref int recvSize
string sendStr, UInt32 sendSize, string recvStr, UInt32 recvSize
StringBuilder sendStr, UInt32 sendSize, ref string recvStr, ref UInt32 recvSize
但是总是会报那个错。到底是该用什么数据类型呢?
...全文
1260 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
wowuqiao 2014-09-01
  • 打赏
  • 举报
回复
SamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesSamplesS
amplesSamplesSamplesSamples
紫舞玥汐 2012-06-20
  • 打赏
  • 举报
回复
感谢 11楼qldsrx 和 5楼foreachif !!!
最后是得到Intptr输出的地址后,在用Marshal.Copy转换到byte[]里的。
因为如果直接用byte[]来获得输出的话只能得到第一byte[0]的值。恐怕原来的C++函数中返回的是地址吧…
qldsrx 2012-06-17
  • 打赏
  • 举报
回复
const等价于C#的readonly 关键字,这里起什么作用不清楚。
紫舞玥汐 2012-06-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
在C++里面,char不一定是字符的意思,等价于C#的byte,要看具体情况,因此char*就等价于C#的byte[],而后面又跟着一个参数来指定前面这个const char*的长度,可见更不可能是字符串了,因为C++里面的字符串是以0x00结尾的二进制数组,遇到0x00自动认为是字符串的结束标志,不需要指定长度,它却指定了,因此可以看出那个不代表传递的是字符串。
[/Quote]

原来如此啊~~受教了!!
那我想是byte[]应该没错了,因为RSendTo这个方法最终是通过socket来收发消息。只是不理解这个const在这里又起什么作用呢。
qldsrx 2012-06-17
  • 打赏
  • 举报
回复
在C++里面,char不一定是字符的意思,等价于C#的byte,要看具体情况,因此char*就等价于C#的byte[],而后面又跟着一个参数来指定前面这个const char*的长度,可见更不可能是字符串了,因为C++里面的字符串是以0x00结尾的二进制数组,遇到0x00自动认为是字符串的结束标志,不需要指定长度,它却指定了,因此可以看出那个不代表传递的是字符串。
紫舞玥汐 2012-06-17
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
你这里面完全看不到String的影子,你用String传递进去肯定是得不到想要的结果了,用int类型都比那个好。至于输出,看不出它对应了什么类型,只有一个dwSize来说明这个类型的长度,因此你只能用byte[]来获取输出,或者直接Intptr得到输出的地址后,自己Marshal.Copy
[/Quote]

((const char*)&pFunc 这个不是string型的么?pFunc在这里是个结构体啊~~
qldsrx 2012-06-17
  • 打赏
  • 举报
回复
你这里面完全看不到String的影子,你用String传递进去肯定是得不到想要的结果了,用int类型都比那个好。至于输出,看不出它对应了什么类型,只有一个dwSize来说明这个类型的长度,因此你只能用byte[]来获取输出,或者直接Intptr得到输出的地址后,自己Marshal.Copy
紫舞玥汐 2012-06-17
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
string sendStr, int sendSize, ref string recvStr, ref int recvSize
上面这个是对应的正确声明
其实楼主的这个error很多时候都是由于typedef struct{
enumPUBLIC enumV;
}PUBLICFunction,*PPUBLICFunction;引起的
这样:
[DllImport("...dll", CallingConvention = CallingConvention.Cdecl)]
[/Quote]

首先感谢5楼,的确是需要这个CallingConvention。
但是,本人确实是对C++不太熟悉,我加上这句之后,虽然不报错了,但是却没有得到正确的返回值。
我想问问是不是我发送的数据错了呢?因为原本C++里的代码是发送一个结构体数据的。代码如下:

DWORD dwSize;
PUBLICFunction pFunc;
pFunc.enumV =GET_ACTIVESIGNALS;
/* 这里的GET_ACTIVESIGNALS = 32,但由于它是个枚举型,我不知道是否可以直接用int型的32?*/
dwSize=0;
*pOutput=NULL;
RSendTo((const char*)&pFunc,(DWORD)(DWORD_PTR)sizeof(pFunc),pOutput,&dwSize);

其中对于PUBLICFumction的定义如下:

typedef struct{
enumPUBLIC enumV;
}PUBLICFunction,*PPUBLICFunction;


那我C#的代码里是不是也应该用一个结构体,然后转换为数据流传参呢?如果是的话,这个时候,参数的类型是否要改变呢?谢谢各位!!
纵横宇宙 2012-06-17
  • 打赏
  • 举报
回复
c++的char是1字节
c#的char是2字节,怎么会对应呢?
wenbin 2012-06-17
  • 打赏
  • 举报
回复
在C++ 中是指常量,在函数内是不能修改该值的。

不过封装成API能成功吗?因为C中没有这个东西哈

所以不用理会它,
九度空间 2012-06-16
  • 打赏
  • 举报
回复
//c++:HANDLE(void *) ---- c#:System.IntPtr
//c++:Byte(unsigned char) ---- c#:System.Byte
//c++:SHORT(short) ---- c#:System.Int16
//c++:WORD(unsigned short) --- c#:System.UInt16
//c++:INT(int) ---- c#:System.Int16
//c++:INT(int) ---- c#:System.Int32
//c++:UINT(unsigned int) ---- c#:System.UInt16
//c++:UINT(unsigned int) ---- c#:System.UInt32
//c++:LONG(long) ---- c#:System.Int32
//c++:ULONG(unsigned long) -- c#:System.UInt32
//c++:DWORD(unsigned long) -- c#:System.UInt32
//c++:DECIMAL ---- c#:System.Decimal
//c++:BOOL(long) ---- c#:System.Boolean
//c++:CHAR(char) ---- c#:System.Char

//c++:LPSTR(char *) ---- c#:System.String
//c++:LPWSTR(wchar_t *) ---- c#:System.String
//c++:LPCSTR(const char *) --- c#:System.String
//c++:LPCWSTR(const wchar_t *) --- c#:System.String

//c++:PCAHR(char *) ---- c#:System.String

//c++:BSTR ---- c#:System.String

//c++:FLOAT(float) ---- c#:System.Single
//c++:DOUBLE(double) ---- c#:System.Double
//c++:VARIANT ---- c#:System.Object
//c++:PBYTE(byte *) ---- c#:System.Byte[]
//c++:BSTR ---- c#:StringBuilder

//c++:LPCTSTR ---- c#:StringBuilder

//c++:LPCTSTR ---- c#:string

//c++:LPTSTR ----
c#:[MarshalAs(UnmanagedType.LPTStr)] string

//c++:LPTSTR ---- c#:StringBuilder

//c++:LPCWSTR ---- c#:IntPtr

//c++:BOOL ---- c#:bool

//c++:HMODULE ---- c#:IntPtr

//c++:HINSTANCE ---- c#:IntPtr

//c++:结构体 ---- c#:public struct 结构体{};

//c++:结构体 **变量名 ---- c#:out 变量名

//C#中提前申明一个结构体实例化后的变量名

//c++:结构体 &变量名 ---- c#:ref 结构体 变量名
//c++:WORD ---- c#:ushort

//c++:DWORD ---- c#:uint

//c++:DWORD ---- c#:int

//c++:UCHAR ---- c#:int

//c++:UCHAR ---- c#:byte

//c++:UCHAR* ---- c#:string

//c++:UCHAR* ---- c#:IntPtr

//c++:GUID ---- c#:Guid

//c++:Handle ---- c#:IntPtr

//c++:HWND ---- c#:IntPtr

//c++:DWORD ---- c#:int

//c++:COLORREF ---- c#:uint

//c++:unsigned char ---- c#:byte

//c++:unsigned char * ---- c#:ref byte

//c++:unsigned char * ----
c#:[MarshalAs(UnmanagedType.LPArray)] byte[]
//c++:unsigned char * ----
c#:[MarshalAs(UnmanagedType.LPArray)] Intptr
//c++:unsigned char & ---- c#:ref byte

//c++:unsigned char 变量名 ---- c#:byte 变量名
//c++:unsigned short 变量名 ---- c#:ushort 变量名
//c++:unsigned int 变量名 ---- c#:uint 变量名
//c++:unsigned long 变量名 ---- c#:ulong 变量名
//c++:char 变量名 ---- c#:byte 变量名

//c++中一个字符用一个字节表示,c#中一个字符用两个字节表示

//c++:char 数组名[数组大小] ----
c#:MarshalAs(UnmanagedType.ByValTStr, SizeConst = 数组大小)]

//c++:char * ---- c#:string

//c++:char * ---- c#:StringBuilder

//c++:char *变量名 ---- c#:ref string 变量名
//c++:char *输入变量名 ---- c#:string 输入变量名
//c++:char *输出变量名 ----
c#:[MarshalAs(UnmanagedType.LPStr)] StringBuilder 输出变量名

//c++:char ** ---- c#:string

//c++:char **变量名 ---- c#:ref string 变量名
//c++:const char * ---- c#:string

//c++:char[] ---- c#:string

//c++:char 变量名[数组大小] ----
c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=数组大小)] public string 变量名;

//c++:struct 结构体名 *变量名 ---- c#:ref 结构体名 变量名

//c++:委托 变量名 ---- c#:委托 变量名

//c++:int ---- c#:int

//c++:int ---- c#:ref int

//c++:int & ---- c#:ref int

//c++:int * ---- c#:ref int

//C#中调用前需定义int 变量名 = 0;

//c++:*int ---- c#:IntPtr

//c++:int32 PIPTR * ---- c#:int32[]

//c++:float PIPTR * ---- c#:float[]

//c++:double** 数组名 ---- c#:ref double 数组名

//c++:double*[] 数组名 ---- c#:ref double 数组名

//c++:long ---- c#:int

//c++:ulong ---- c#:int

//c++:UINT8 * ---- c#:ref byte

//C#中调用前需定义byte 变量名 = new byte();
//c++:handle ---- c#:IntPtr

//c++:hwnd ---- c#:IntPtr

//c++:void * ---- c#:IntPtr

//c++:void * user_obj_param ----
c#:IntPtr user_obj_param

//c++:void * 对象名称 ----
c#:([MarshalAs(UnmanagedType.AsAny)]Object 对象名称

//c++:char,INT8,SBYTE,CHAR -- c#:System.SByte
//c++:short, short int, INT16, SHORT ---- c#:System.Int16

//c++:int, long, long int,INT32, LONG32, BOOL , INT ---- c#:System.Int32

//c++:__int64,INT64,LONGLONG -- c#:System.Int64

//c++:unsigned char, UINT8, UCHAR , BYTE ---- c#:System.Byte

//c++:unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t ---- c#:System.UInt16

//c++:unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT
---- c#:System.UInt32

//c++:unsigned __int64, UINT64, DWORDLONG, ULONGLONG
---- c#:System.UInt64

//c++:float,FLOAT -- c#:System.Single

//c++:double, long double, DOUBLE ---- c#:System.Double

//Win32 Types ---- CLR Type

//Struct需要在C#里重新定义一个Struct

//CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);

//unsigned char** ppImage替换成IntPtr ppImage
//int& nWidth替换成ref int nWidth

//int*, int&, 则都可用 ref int 对应

//双针指类型参数,可以用 ref IntPtr

//函数指针使用c++: typedef double (*fun_type1)(double); 对应 c#:public delegate double fun_type1(double);

//char* 的操作c++: char*; 对应 c#:StringBuilder;
//c#中使用指针:在需要使用指针的地方 加 unsafe

//unsigned char对应public byte

WAN 2012-06-15
  • 打赏
  • 举报
回复
string sendStr, int sendSize, ref string recvStr, ref int recvSize
上面这个是对应的正确声明
其实楼主的这个error很多时候都是由于CallingConvention引起的
这样:
[DllImport("...dll", CallingConvention = CallingConvention.Cdecl)]
__天涯寻梦 2012-06-15
  • 打赏
  • 举报
回复
指针是没有绝对对应的,要看函数里怎么处理这个参数
ParanoidKing 2012-06-15
  • 打赏
  • 举报
回复
输入参数的话string应该也可以,指定对CharSet就行。输出参数要用IntPtr或StringBuider。试试这样
string sendStr, UInt32 sendSize, StringBuider recvStr, ref UInt32 recvSize
wenbin 2012-06-15
  • 打赏
  • 举报
回复
const char *pszBuffer,DWORD dwSize,chsr **pszOutPut,DWORD *pdwRecv
这个不是字符串,是字节流

IntPtr pszBuffer, int dwSize, out IntPtr pszOutPut, out pdwRecv
IntPtr里面的东西可以使用Marshal类里面的Copy函数拿出来
mizuho_2006 2012-06-15
  • 打赏
  • 举报
回复
http://blog.163.com/xiaozhi797@126/blog/static/62440288201231341344512/

111,126

社区成员

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

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

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