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 会导致意外的异常、损坏或数据丢失。

参数传递应该是正确的,不知道是怎么回事。
请高手帮帮忙!!!
...全文
629 18 打赏 收藏 转发到动态 举报
写回复
用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就可以了。
随着元宇宙概念兴起与虚拟数字人技术快速发展,虚拟主播、在线教育虚拟助教、元宇宙社交等应用场景对实时动作表情驱动系统提出更高需求。当前主流动作捕捉方案多依赖专业光学动捕设备或深度相机,设备成本高昂、部署复杂,难以在普通用户场景普及。本研究设计并实现一套基于普通单目摄像头的虚拟数字人实时动作表情驱动系统,旨在降低数字人内容生产门槛。系统采用Unity作为主开发引擎,结合Blender进行数字人模型构建与BlendShape表情系统制作,使用MediaPipe框架实现人脸关键点检测与人体姿态估计,通过C#脚本完成实时数据处理与渲染控制。系统包含五个关键模块:人脸关键点检测(MediaPipe Face Mesh提取468个关键点)、人体姿态估计(MediaPipe Pose识别33个骨骼关键点)、表情迁移映射、动作平滑优化(卡尔曼滤波与贝塞尔曲线插值消除抖动)、实时渲染(60fps流畅渲染,支持直播推流与视频录制)。实验结果表明,系统在普通笔记本上可实现60fps实时驱动,人脸关键点检测准确率达98.7%,人体姿态估计平均误差小于5像素,表情迁移相似度达92.3%。 【课程报告内容】 摘要 第1章 绪论 第2章 相关技术与理论基础 第3章 系统架构设计 第4章 关键模块设计与实现 第5章 实验与结果分析 第6章 总结与展望 参考文献
内容概要:本文提出了一种基于蒙特卡洛模拟与拉格朗日松弛法的分散式优化策略,用于解决电动汽车充电站在分时电价机制下的有序充电调度问题。通过蒙特卡洛方法模拟电动汽车充电行为的随机性,生成多样化负荷场景,构建以降低电网负荷波动和用户充电成本为目标的优化模型;采用拉格朗日松弛法对耦合约束进行解耦,实现分布式求解,在保障用户隐私的同时提升计算效率。文中设计了详细的仿真场景,系统分析了该调度策略对电网负荷特性和用户经济性的影响,验证了所提方法在实际应用中的有效性与可行性。; 适合人群:具备电力系统运行、优化算法理论及Matlab编程能力的研究生、科研人员以及从事智能电网与电动汽车相关领域的工程技术人员。; 使用场景及目标:①应用于城市规模化充电站集群的有序充电管理,实现电网“削峰填谷”;②为电力公司制定科学合理的分时电价政策提供量化分析工具;③支撑智能电网中需求侧资源的分布式协同优化调度研究与系统设计。; 阅读建议:建议结合提供的Matlab代码深入理解算法实现流程,重点掌握蒙特卡洛场景生成机制与拉格朗日松弛迭代求解过程,可通过调整参数设置复现不同工况下的仿真结果,以深化对分散式优化机制与调度效果之间关系的理解。
内容概要:本文研究了基于阶跃响应的V-Tiger自动增益调整PID控制器优化方法,并提供了完整的Matlab代码实现。通过深入分析PID控制的核心性能指标与V-Tiger控制器的动态特性,提出了一种融合阶跃响应特征提取与多目标协同优化的自动整定方案,设计了具备自适应迭代校正能力的优化机制,有效提升了控制系统的响应速度、稳定性和抗干扰能力。文中系统阐述了整定原理、算法架构设计及性能验证流程,通过仿真实验充分验证了该方法在复杂工业控制场景下实现高精度参数自整定的可行性与优越性,为智能PID控制提供了可复现、可拓展的技术路径。; 适合人群:具备自动控制理论基础和Matlab编程能力,从事控制工程、自动化、电气工程等领域研究的研发人员及高校研究生。; 使用场景及目标:①应用于需要高精度PID参数整定的工业控制系统中,如电机驱动、温度控制、电力电子变换器等;②为科研人员提供一种可复现、可扩展的智能PID整定方法,用于提升系统动态性能与鲁棒性;③作为教学案例帮助学生理解PID整定原理与现代优化算法的融合应用。; 阅读建议:建议读者结合文中的Matlab代码逐模块运行与调试,重点关注阶跃响应特征提取与增益优化策略的实现逻辑,同时可尝试将其应用于实际控制系统中进行对比验证,以深化对自动整定机制的理解。

111,129

社区成员

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

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

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