将多维数组从 c# 编组到 delphi

问题描述

我正在将 lib 从 delphi 重写为 c#。在delphi客户端调用library方法,参数如下

T:=VararrayCreate([1,2,1,1],varDouble);
T[1,1]:=Tmin;
T[2,1]:=Tmax;

我尝试像这样将相同的数组传递给 c#:

 Array tVector = Array.CreateInstance(typeof(double),new[] { 2,1 },new[] { 1,1 });
 tVector.SetValue(Tmin,1);
 tVector.SetValue(Tmax,1);

 object T = tVector;

然后扔掉

System.Runtime.InteropServices.SEHException:“外部组件抛出异常。”

然后像这样尝试:

 Array tVector1 = Array.CreateInstance(typeof(double),new[] { 1 },new[] { 1 });
 Array tVector2 = Array.CreateInstance(typeof(double),new[] { 1 });
 Array tVector = Array.CreateInstance(tVector1.GetType(),new[] { 2 },new[] { 1 });

 tVector.SetValue(tVector1,1);
 tVector.SetValue(tVector2,2);

 object T = tVector;

然后扔掉

System.Runtime.InteropServices.SafeArrayTypeMismatchException:“指定的数组不是预期的类型。”

初始化条件:

c#调用delphi方法

function  call (hModel: TModelHandle; const FunName: variant; var Params: variant; var Res: variant): TRetCode; stdcall;

Params 是一维变量数组。我准备如下:

public object Call(string functionName,params object[] parameters)
{
        object res = new();

        object funName = functionName;
        
        Array endParamsArray = Array.CreateInstance(typeof(object),new[] {parameters.Length},new[] {1});
        Array.copy(parameters,endParamsArray,parameters.Length);
        object endParams = endParamsArray;
        
        var rc = call(hModel,ref funName,ref endParams,ref res);

        if (rc != TRetCode.rcOK)
            error(rc);

        return res;
}

然后我打电话:

 object T = tVector;

 PM.Call("funname",ID,Name,T,RamStab,Ktrans,sec_overcoming);

当传递的参数很简单:int、string 等时,一切正常。但是传递一个数组我得到一个异常

这是 Delphi 上的客户端代码,其中一切正常:

 w:='funname'; FunName:=w;
Params:=VararrayCreate([1,6],varVariant);
Params[1]:=ID;
Params[2]:=Name;
T:=VararrayCreate([1,1]:=Tmax;
Params[3]:=T;
Params[4]:=RamStab;
Params[5]:=Ktrans;
Params[6]:=sec_overcoming;
rc:=PM.call(PM.hModel,FunName,Params,Res);
Bar:=PM.getobject(Name);
if Bar=nil then
  error('create');

解决方法

找到您所引用的内容:mov cr,reg

function call (hModel: TModelHandle; const FunName: variant; var Params: variant; var Res: variant): TRetCode; stdcall;

TRetCode __stdcall call (TModelHandle hModel,variant *FunName,variant *Params,variant *Res);

哪里

TRetCode = 整数 - 完成代码。

TModelHandle = THandle – 指向模型的指针;

所以我想说 TModelHandle 是一个 IntPtr(32 位有 32 位进程,64 位有 64 位进程)。所以:

[DllImport(@"Yourdll",CallingConvention = CallingConvention.StdCall)]
public static extern int call(IntPtr hModel,ref object funName,ref object @params,ref object res);

public static object Call(string functionName,params object[] parameters)
{
    object res = null;

    object funName = functionName;

    Array endParamsArray = Array.CreateInstance(typeof(object),new[] { parameters.Length },new[] { 1 });
    Array.Copy(parameters,endParamsArray,parameters.Length);
    object endParams = endParamsArray;

    var rc = call(hModel,ref funName,ref endParams,out res);

    return res;
}

我已经用为 C++ 提议的签名构建了一个 C#->C++ 代码,并且它可以正常工作。参数传递正确,res正确传出。

double Tmin = double.MinValue;
double Tmax = double.MaxValue;

int ID = 1;
string Name = "Foo";
double RamStab = 5;
long Ktrans = 3;
int sec_overcoming = 2;

Array tVector = Array.CreateInstance(typeof(double),new[] { 2,1 },new[] { 1,1 });
tVector.SetValue(Tmin,1,1);
tVector.SetValue(Tmax,2,1);

object response = Call("Hello world",ID,Name,tVector,RamStab,Ktrans,sec_overcoming);