当前位置:编程学习 > C#/ASP.NET >>

关于C#调用OCX的方法,传递数组参数的问题

小弟正在做一个设备的接口开发,是用VB写的OCX,我用C#调用有一个方法调用一直不正确,请大师指导一下:
添加OCX引用后,其方法在C#中看到的定义如下:
GetAllData(string ip, ref int rowCount, ref string[] gra_Date, ref string[] gra_No);

方法的作用是:从设备返回所有数据,rowCount是记录数,gra_Date是日期((应定义有 10 个元素的数组),gra_No是编号((应定义有 10 个元素的数组),

厂家的技术支持提供了VB的DEMO,能正确返回结果,无C#的(问了说不懂C#,没办法,我们必须在C#中做)。

该方法在C#中一直没成功返回结果。我查了一下网上的资料,好像说OCX是非托管代码,要进行封装什么的,不懂啊,这个问题已经折腾1个星期了,请各位大侠指教啊,不然要失业了。
谢谢!
--------------------编程问答-------------------- 既然能添加COM引用,就已经可以调用了。你不是已经看到方法列表了么。

你的调用代码是怎么写的呢? --------------------编程问答-------------------- 一个连C#都不懂的厂商,他的产品你也敢用?遇到问题你找谁支持去?招聘一个C#程序员也不贵,这个厂商连这个钱都出不起。 --------------------编程问答-------------------- 以前曾经做过,应该不会有问题

你把调用OCX的代码贴出来

看看是不是OCX的调用路径没有写对?一定要指定到最终的目录 --------------------编程问答-------------------- 最关键的是,你用了这种作坊的东西,底下有得扯皮呢。你说是它设备的故障,他说是你调用不正确。你说我调给你看,他说我不懂C#。好吧,你们就扯去吧。 --------------------编程问答-------------------- caozhy说的问题确实存在,小公司的技术保障很难实现长久。

--------------------编程问答-------------------- 理论上说,.NET可以完全向下兼容COM调用。但是,没有兼容性问题的软件,只停留在理论上。 --------------------编程问答--------------------
引用 1 楼 fangxinggood 的回复:
既然能添加COM引用,就已经可以调用了。你不是已经看到方法列表了么。

你的调用代码是怎么写的呢?


int count = 0;
string[] gra_Date = new string[14];
string[] gra_No = new string[14];

int retVal = tbocx.GetAllData("192.168.0.100", ref count, ref gra_Date, ref gra_No);

正确执行,retVal应该返回为0, 数据是保存在数组中的。
我现在执行返回结果为负数。

OCX的其它方法都调用正确,就只有这个方法的参数是数组,其它方法的参数都是简单类型。

--------------------编程问答-------------------- 我用DELPHI 6测试过这个方法,是可以调用成功的。DELPHI中看到的数组参数都是SafeArray类型,
C#我是折腾了一个星期都没解决到。  --------------------编程问答-------------------- C#所使用的.Net FrameWork SDK都是受管代码,而对于那些COM组件来说,他们都是非受管代码(Unmanaged Code),所以这些COM组件要能够被VB.NET和C#使用,必须实现自身从非受管代码到受管代码的转换。在.Net框架中提供了一个程序来专门实现这种转换,这个文件就是"Aximp.exe",如果你把.Net FrameWork SDK安装在"C"盘,那么在"C:\Program Files\Microsoft.NET\FrameworkSDK\Bin"目录中,就可以找到这个文件。

假设你的文件是tb.ocx

运行:Aximp c:\tb.ocx

运行上述命令后就可以实现转换,并在当前目录中产生"tb.dll"和"Axtb.dll"二个文件。

添加引用Axtb.dll --------------------编程问答-------------------- 不是应定义10个元素么?为什么定义为14?

另外,能返回负数,说明你能调用。 --------------------编程问答-------------------- 直接引用就好了,VS会自动进行转换

确定不是内部逻辑问题,或IP访问失败,???

--------------------编程问答--------------------
引用 9 楼 ly302 的回复:
C#所使用的.Net FrameWork SDK都是受管代码,而对于那些COM组件来说,他们都是非受管代码(Unmanaged Code),所以这些COM组件要能够被VB.NET和C#使用,必须实现自身从非受管代码到受管代码的转换。在.Net框架中提供了一个程序来专门实现这种转换,这个文件就是"Aximp.exe",如果你把.Net FrameWork SDK安装在"C"盘,那么在"C:\Prog……


这个已经做了,OCX的其它方法我都能正确调用 --------------------编程问答--------------------
引用 11 楼 wknight_it 的回复:
直接引用就好了,VS会自动进行转换

确定不是内部逻辑问题,或IP访问失败,???


可以确定不是IP的问题,其它方法是可以正确调用的,

问题应该是出在托管与非托管上,请了解的大侠支招啊 --------------------编程问答-------------------- 帮顶,也关心这个问题 --------------------编程问答--------------------
引用 10 楼 fangxinggood 的回复:
不是应定义10个元素么?为什么定义为14?

另外,能返回负数,说明你能调用。


是14位,输入错误,返回负数就是说明中间的参数传递不正确。 --------------------编程问答-------------------- 如果是SafeArray,你的函数签名是错的,应该是:
GetAllData(string ip, ref int rowCount, ref object gra_Date, ref object gra_No);
调用时:
int count = 0;
object gra_Date = new VariantWrapper("日期");
object gra_No = new VariantWrapper("编号");
int retVal = tbocx.GetAllData("192.168.0.100", ref count, ref gra_Date, ref gra_No);
--------------------编程问答--------------------
引用 16 楼 jshi123 的回复:
如果是SafeArray,你的函数签名是错的,应该是:
GetAllData(string ip, ref int rowCount, ref object gra_Date, ref object gra_No);
调用时:
int count = 0;
object gra_Date = new VariantWrapper("日期");
object gra_No = new Va……


你的函数签名是错的? 
我在C#中添加OCX引用后,声明OCX对象后,它的方法的参数类型就是string[],不是object啊。 --------------------编程问答-------------------- 那就是底层的问题了。VB的示例呢? --------------------编程问答-------------------- 用TypeLib Viewer看下IDL中函数原型的定义是什么
运行Visual Studio程序组下面Microsoft Windows SDK Tools -> OLE/COM Object View
File->View TypeLib... --------------------编程问答-------------------- 实在不行,就是用delphi再封装一次吧。
c#在和ocx的交互上,数据类型确实是个很麻烦的东西。
--------------------编程问答-------------------- 你把ocx先添加到左边的工具栏选项卡里,再把它拖到Form的面板上!
你在右边的引用栏,点击这个ocx,看看这个方法到底是不是你说的这样:
GetAllData(string ip, ref int rowCount, ref string[] gra_Date, ref string[] gra_No);

如果确实是这样,你把在C#中的代码贴出来看看。。。。

--------------------编程问答--------------------
引用 21 楼 sdl2005lyx 的回复:
你把ocx先添加到左边的工具栏选项卡里,再把它拖到Form的面板上!
你在右边的引用栏,点击这个ocx,看看这个方法到底是不是你说的这样:
GetAllData(string ip, ref int rowCount, ref string[] gra_Date, ref string[] gra_No);

如果确实是这样,你把在C#中的代码贴出来看看。。。。


通过添加控件的方法,在C#中看到这个方法的定义:
GetAllData(string ip, ref int rowCount, ref Array gra_Date, ref Array gra_No);

通过Aximp.exe生成DLL添加引用,看到的就是string[],而不是Array.

提供的VB,DEMO,代码很简单,    
    Dim gra_count As Long                  
    Dim gra_Date(14) As String
    Dim gra_No(14) As String
    Me.OCX1.GetAllData(IP, Record_Num, gra_Date(), gra_No()) --------------------编程问答-------------------- 那你模仿VB的方式:

int count=0;
string[] gra_Date=new string[14]{""};
int gra_No=0;
string[] gra_No=new string[14]{""};

int retVal = tbocx.GetAllData("192.168.0.100", ref count, ref gra_Date, ref gra_No);
--------------------编程问答-------------------- 你用 vb包装成一个类库给c#调用 --------------------编程问答-------------------- 他的参数是要一个String的引用, 或者准确点说是要一个byte数组,你却定义一个string数组,肯定出错了,你可以试下:
byte[] tempbyte = new byte[50];
int retVal = tbocx.GetAllData("192.168.0.100", ref count, tempbyte[0], tempno[0]);
--------------------编程问答-------------------- 关键是看你添加引用后, 他的函数声明式是如何的, 我想有可能就是ref string --------------------编程问答-------------------- 这个就是找厂家要的OCX的VB源代码中的函数定义:
Public Function GetAllData(ByVal IP As String, ByRef  RowCount As Long, 
                          ByRef GRA_Date() As String, ByRef GRA_No() As String) As Long

我通过Aximp.exe生成DLL添加引用,看到的参数类型就是string[]。难道是Aximp.exe生成有误?
GetAllData(string ip, ref int rowCount, ref string[] gra_Date, ref string[] gra_No);




--------------------编程问答-------------------- 要不把你的那个OCX放上来吧,大家可以一起看看,按他的函数声明, 就是一个string --------------------编程问答-------------------- 这类似的问题我碰到过,我蛮同意TragicGuy的意见。你可以改为string 或是 ref byte【】试试。
另外,你的疑问Aximp.exe生成有误时完全可能的。俺用BCB时IDE自带的工具生成的代码连头文件的声明都是错的,所有的注释被它当做代码。 --------------------编程问答-------------------- 路过 帮顶 --------------------编程问答-------------------- weiguan,kankan,xuexixia --------------------编程问答--------------------
引用 2 楼 caozhy 的回复:
一个连C#都不懂的厂商,他的产品你也敢用?遇到问题你找谁支持去?招聘一个C#程序员也不贵,这个厂商连这个钱都出不起。

笑话,谁规定设备厂商一定要懂C#? --------------------编程问答-------------------- 工具栏中-选择项-COM组件,添加需要的OCX,然后直接像控件一样使用,另外要注意配置环境变量,刚做过一个加载C做的OCX,应该类似,希望有帮助~~~ --------------------编程问答-------------------- 如果要调用非托管代码 先通过DllImport导入dll,然后通过关键字extern使用 以前在做短信猫的时候使用过 不知道这个方法适不适合你 --------------------编程问答-------------------- ----------------------------------
int count = 0;
string[] gra_Date = new string[14];
string[] gra_No = new string[14];

int retVal = tbocx.GetAllData("192.168.0.100", ref count, ref gra_Date, ref gra_No);

正确执行,retVal应该返回为0, 数据是保存在数组中的。
我现在执行返回结果为负数。

OCX的其它方法都调用正确,就只有这个方法的参数是数组,其它方法的参数都是简单类型。
----------------------------------------------------------------------
    这里gra_Date和gra_No只是分配了制定数目的引用,而没有分配sring对象,我怀疑是不是这儿的代码问题。
string[] gra_Date = new string[14];
for (int i = 0; i < 14; ++i)
{
    gra_Date[i] = new string();     
}
string[] gra_No = new string[14];
for (int i = 0; i < 14; ++i)
{
    gra_No[i] = new string();
}
--------------------编程问答-------------------- 帮顶!!! --------------------编程问答-------------------- vb里面调用正确,而C#里面出错,
VB是VS里自带的那个吗?
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,