C#调用ocx控件的方法,传递ref byte参数出错

f7anty 2012-02-12 10:29:04
OCX使用C++写的
方法为:char MyFunc( unsigned char * src , unsigned char * result)。

我现在在一个C#程序里使用这个方法(ActiveX控件已经导入并实例化,比如叫ax),MyFunc自动生成的原型是
byte MyFunc( ref byte src , ref byte result)。
我是这样调用的,用C#
byte[] src=new byte[256];
byte[] result=new byte[256];
ax.MyFunc(ref src[0], ref result[0])

出现异常:
检测到 InvalidVariant
Message: 从非托管 VARIANT 转换为托管对象的过程中检测到无效 VARIANT。将无效 VARIANT 传递给 CLR 会导致意外的异常、损坏或数据丢失。

参数传递应该是正确的,不知道是怎么回事。
请高手帮帮忙!!!
...全文
541 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lionheartch 2014-05-26
  • 打赏
  • 举报
回复
遇到同样的问题?请问楼主最后是用什么办法解决的呢?
WAN 2012-03-10
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/en-us/library/e753eftz.aspx
WAN 2012-02-15
  • 打赏
  • 举报
回复
客气了
没能帮你解决,我才是过意不去
最好是能找些OCX或者COM专家咨询一下了
f7anty 2012-02-15
  • 打赏
  • 举报
回复
谢谢foreachif的耐心回答,我再试试。为这拖了这么多天心里真是过意不去55555……
WAN 2012-02-15
  • 打赏
  • 举报
回复
我对COM了解的不多。但byte MyFunc(ref byte src, ref byte result)应该是可改的,而且似乎方法还不只一种
这里看到一种比较简单的,不让它自动生成接口声明,而是使用ComImportAttribute手动声明:
http://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.comimportattribute.aspx
f7anty 2012-02-14
  • 打赏
  • 举报
回复
我知道ref是引用类型,但是传递的时候ref src[0]传的就是数组的首地址不是src[0]单个字节.现在不知道是ocx方法里面的问题还是这边调用时出现的问题
f7anty 2012-02-14
  • 打赏
  • 举报
回复
ocx使用C++写的,其中函数的原型为
unsigned char MyFunc( unsigned char * src , unsigned char * result),
在C++传递的是数组BYTE SRC[256],RESULT[256]
我调用这个ocx,这个函数就被转换为byte MyFunc(ref byte src, ref byte result)
调用就存在参数传递的问题
Message: 从非托管 VARIANT 转换为托管对象的过程中检测到无效 VARIANT。将无效 VARIANT 传递给 CLR 会导致意外的异常、损坏或数据丢失
这个问题不知道是ocx本身代码的问题还是我这边调用的问题。
网上说数据类型用BSTR、LPTSTR比较容易被调用,被这个问题困扰了好多天,5555555
WAN 2012-02-14
  • 打赏
  • 举报
回复
C++中的函数原型不需要改

引用时被自动转换为byte MyFunc(ref byte src, ref byte result)
--这个改不了吗?这就难办了,这是关键

unsigned char* 在C++中是 无符号字符指针,但其指向的实际内容并不明确,可以指向 一字节的无符号字符,也可以认为是 数组首地址 指向一个无符号字符数组。
这就造成在C#调用时产生了二义:当作字符,则应该以 引用传递 byte 这一 值类型;当作数组,则应该以 值传递 byte数组 这一 引用类型。
楼主的 MyFunc自动生成 显然选择了前者。
其实楼主最初的代码,无论是 MyFunc自动生成的原型 或是 ax.MyFunc(ref src[0], ref result[0]) 调用,单从语法上来讲都是符合规范的。问题是这种方式仅仅是封送了 一个byte ,而非一个 byte数组 ,这样的话,如果C++中试图把传入的指针当作数组首地址(而非无符号字符指针)访问“数组”的第2、3…个元素时就必然越界
WAN 2012-02-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 f7anty 的回复:]
参数为ref byte类型,函数byte MyFunc( ref byte src , ref byte result)
如果byte[] src=new byte[256];
byte[] result=new byte[256];
ax.MyFunc(ref src[0], ref result[0])
这样传递的是整个数组,不是一个字节。这样应该是正确的,不知道为什么还是报错……
[/Quote]

调用时:
ax.MyFunc(ref src, ref result)

数组在C#中是引用类型,非值类型
f7anty 2012-02-14
  • 打赏
  • 举报
回复
因为现在调用的是别人写的ocx,其中函数的原型为
unsigned char MyFunc( unsigned char * src , unsigned char * result)
引用时被自动转换为byte MyFunc( ref byte src , ref byte result)
这个我也改不了,现在调用时出现问题,不知道怎么传递参数。。。纠结

qq181818228 2012-02-14
  • 打赏
  • 举报
回复
纠正一下,手误,CHAR转成byte[]
qq181818228 2012-02-14
  • 打赏
  • 举报
回复
8楼正解,我经常用到C++的DLL,基本上char就转为string
C++ 原型
PXRCPU_API int __stdcall PXRSHNMTeleCheckBlank(HANDLE hComm,int iNodeID,unsigned char *cReceiveData,int *iReceiveDataLen,unsigned int iTimeout);

c#
[DllImport("PXRCPU.dll")]
public static extern int PXRSHNMTeleCheckBlank(int hComm, int iNodeID, byte[] cReceiveData,
ref int iReceiveDataLen, uint iTimeout);

WAN 2012-02-14
  • 打赏
  • 举报
回复
MyFunc生成的原型应该改为:
byte MyFunc([In, Out] byte[] src, [In, Out] byte[] result);
调用时:
ax.MyFunc(src, result)
WAN 2012-02-14
  • 打赏
  • 举报
回复
我说的是在C#中“数组是引用类型”
与C++不同,ref src[0]不代表数组的首地址(哪怕在托管内存中,数组元素实际是按序排列的),而仅仅是src[0]这个字节的引用传递而已
C#已没有“数组的首地址”这个说法了
JoeBlackzqq 2012-02-13
  • 打赏
  • 举报
回复
byte MyFunc( ref byte src , ref byte result)这种原型的话,只能传递一个字节的数据byte.


这个函数在OCX中的声明就不太合适,应该改为:
char MyFunc( BSTR * src , BSTR * result);

因为不同语言数据类型的不同,所以在OCX中传递字符串,应该尽量选择BSTR.
f7anty 2012-02-13
  • 打赏
  • 举报
回复
ref是系统已经转换过来的,只能这样调用
f7anty 2012-02-13
  • 打赏
  • 举报
回复
参数为ref byte类型,函数byte MyFunc( ref byte src , ref byte result)
如果byte[] src=new byte[256];
byte[] result=new byte[256];
ax.MyFunc(ref src[0], ref result[0])
这样传递的是整个数组,不是一个字节。这样应该是正确的,不知道为什么还是报错!!!
threenewbee 2012-02-12
  • 打赏
  • 举报
回复
不应该传ref,直接传string就可以了。

111,092

社区成员

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

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

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