错误提示:
project project11.exe raised exception class EOleException with message 秩为0的 SafeArray 被传递到需要秩为1的数组的方法中。 Delphi代码如下:
unit Unit10;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,     activex,
  DB, ADODB,Grids, DBGrids, DBClient, StdCtrls, Provider,
  frmByteArrayToDelphi_TLB,  Dialogs;type
  TForm10 = class(TForm)
    Button1: TButton;
    DBGrid1: TDBGrid;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;  Type 
    byteArrayP=^byteArray;
    byteArray=array   [0..0]   of   byte;
    type
    mybuffer=array [0..1023] of byte;
var
  Form10: TForm10;implementation{$R *.dfm}procedure TForm10.Button1Click(Sender: TObject);
var
{
mydataset:tclientdataset;
mydatasource:tdatasource;
myprovider:  tdatasetprovider;
myquery:tadoquery;
sqlcmd:TStringList;ms1,ms2,ms3:TMemoryStream;
}ttest:Interface1;a,b, len:integer;
buf:mybuffer;
s:string;
//buf2:bytearrayp;buf3:psafearray;begin
//buf2:=allocmem(1024);
//zeromemory(buf2,1024);
buf3:=allocmem(1024);
zeromemory(buf3,1024);
ttest:=CoForm1.Create() AS INTERFACE1;len:=  ttest.getByteArray ; //正常返回 1024;
ttest.fillBytes(buf3); //这里报错:秩为0的 SafeArray 被传递到需要秩为1的数组的方法中end;end.上述代码调用 VS C# dll ,读取一个数组的长度(该方法正常),填充一个byte[](该方法报错);
VS C# dll 的代码如下:
1、接口代码using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace frmByteArrayToDelphi
{
    [Guid("208F6752-E99B-4614-857B-0DA442C338C2")]
    public  interface Interface1
    {
       int  getByteArray();
        void fillBytes(byte[] btz);
    }
}
Class代码:using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace frmByteArrayToDelphi
{
    [Guid("2F6CC041-F319-408D-A544-C4CF5930D21E")]
    public partial class Form1 : Form, Interface1
    {
        public Form1()
        {
            InitializeComponent();
        }        private void button1_Click(object sender, EventArgs e)
        {
       //  byte [] mybt=getByteArray ();
         
       }        byte[] btTest = new byte[1024];        public void setByteArray()
        {
            for (int i = 0; i < btTest.Length; i++)
            {
                btTest[i] = (byte )i;            }
        }        public int  getByteArray()
        {
            setByteArray();
            return btTest.Length ;
        }        public void  fillBytes(byte[] btz)
        {
            for (int i = 0; i < btz.Length; i++)
            {
                btz [i ]=(byte)i;
            }
         // return btz ;
        }
    }
}上述vsC# dll 编译和注册均正常,Delphi 6调用也正常。在delphi中执行fillBytes(buf3) 时候报错:
 project project11.exe raised exception class EOleException with message 秩为0的 SafeArray 被传递到需要秩为1的数组的方法中。 附:《Delphi调用vs dll的步骤》
=====================《Delphi调用vs dll的步骤》===============================
1、编写VS dll
1.1 获取[Guid("xxx-xxx-xxx-xxx-xx0a")]
1.2 按照如下形式写接口 和 类
---------------------------------------
using System.Runtime.InteropServices;
[Guid("xxx-xxx-xxx-xxx-xx0a")]
public interface IAddInterface//自定义接口名字
{
int Add(int i1, int i2);
}
---------------------------------------
using System.Runtime.InteropServices;[Guid("xxx-xxx-xxx-xxx-xx02")]
public class SimpleDLL : IAddInterface//根据需要添加其他父类
{
public int Add(int i1, int i2)
{
return i1+i2;
}
}
1.3编译属性上 选择 对COM可见 
1.4编译生成SimpleDll.dll
------------------------------------------
2、 注册dll
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm SimpleDll.dll /tlb:Add.tlb
产生.tlb文件3、在delphi中添加.tlb文件(注意选择register类型)3.1. Open Delphi (in my case 2009) and press menu "View / Registered Type Library"3.2. Use the search feature to confirm that the name is not registered (if any) and Press "Register" and choose the file "Add.tlb" - read the message resulted by the action (if successful, continue further)3.3. Press menu "Component / Import Component", will lead you to wizard to have yourself the _TLB.PAS file
3.4、. On the wizard choose the Registered Class and press next - now (very important) make sure that the Class Name(s) / Non-editable editbox comes up the names that you have put in the C# public
3.5. Press Finish, now the _TLB.PAS file should be present along with any support files produced by the import action4、Delphi下编写调用代码如下格式
procedure TForm1.Button1Click(Sender: TObject);
var
intfRef: IAddInterface;
result: Integer;
begin
intfRef := CLASS_SimpleDLL_.Create() as IAddInterface;
result := intfRef.Add(2, 2);
end;
(注:3.5后会在工程中添加一个新的单元 dll_TLB单元,要引进来)
===============================《完毕》========================================

解决方案 »

  1.   

    跨语言传数组要用Variant,你这样传数组是有问题的。
      

  2.   

    创建变体数组用VarArrayCreate函数。
      

  3.   

    请教sqldebug_fan兄台,烦劳兄台给在下检查一下,是C# dll 写的不妥,还是Delphi 的代码 需要修改?
    可否给出简单的示例 代码?
    谢谢
      

  4.   

    从两个语言角度来说都没错,只是两个语言使用的内存管理不一样,这样就需要使用一致的接口,可以用COM
      

  5.   

    按照兄台sqldebug_fan的说法,我使用了Variant,代码如下,执行过了那关键的一步,后面又不知道如何把数据从Variant里放回 array[0..1023] of byte中。犯难中
    C# dll 代码没有调整,delphi代码调整如下:unit Unit10;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,     activex, { Variants,}
      DB, ADODB,Grids, DBGrids, DBClient, StdCtrls, Provider,
      frmByteArrayToDelphi_TLB,  Dialogs;type
      TForm10 = class(TForm)
        Button1: TButton;
        DBGrid1: TDBGrid;
        Edit1: TEdit;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  Type
        byteArrayP=^byteArray;
        byteArray=array   [0..0]   of   byte;
        type
        mybuffer=array [0..1023] of byte;
    var
      Form10: TForm10;implementation{$R *.dfm}
    {
    function   VarToByteArr(Value:   Variant;   var   Buffer:   Pointer):   Integer;
    var 
        P:   Pointer; 
        Len:   Integer; 
    begin 
        P   :=   VarArrayLock(Value); 
        try 
            Result   :=   VarArrayHighBound(Value,   1);
            if   Result   =   0   then 
                raise   Exception.Create( 'Value不是数组变量 '); 
            GetMem(Buffer,   Result);         
            Move(P^,   Buffer^,   Result); 
        finally 
            VarArrayUnLock(Value); 
        end;
    end;
     }
    procedure TForm10.Button1Click(Sender: TObject);
    var
    ttest:Interface1;
    a,b, len:integer;
    buf:mybuffer;
    s:string;
    buf3:psafearray;
    var
    Arr: Variant;begin
    //buf2:=allocmem(1024);
    //zeromemory(buf2,1024);
    buf3:=allocmem(1024);
    zeromemory(buf3,1024);Arr := VarArrayCreate([0, 1023],varbyte );ttest:=CoForm1.Create() AS INTERFACE1;len:=  ttest.getByteArray ; //正常返回 1024;
    ttest.fillBytes(PSafeArray(VarArrayAsPSafeArray(Arr))); // 这一步能被执行,但是看不到Arr里面的内容。 // VarToByteArr(arr,pointer(buf));
    //接下来让我犯难的是 如何把 Arr 中的数据 放回 buf中?end;end.
      

  6.   

    问题解决,可以结贴散分。
    谢谢SQLDebug_Fan兄台。
    最后代码如下:
    VS C# DLL代码
    1接口代码:using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    namespace frmByteArrayToDelphi
    {
        [Guid("208F6752-E99B-4614-857B-0DA442C338C2")]
        public  interface Interface1
        {
            byte[] getByteArray();()//返回值从 int 改为 byte[]       void fillBytes(byte[] btz);
        }
    }
    Class代码:using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    namespace frmByteArrayToDelphi
    {
        [Guid("2F6CC041-F319-408D-A544-C4CF5930D21E")]
        public partial class Form1 : Form, Interface1
        {
            public Form1()
            {
                InitializeComponent();
            }        private void button1_Click(object sender, EventArgs e)
            {
                byte[] mybttest = new byte[1000];
                fillBytes(mybttest);
                MessageBox.Show("dsdf");
           //  byte [] mybt=getByteArray ();
             
           }        byte[] btTest = new byte[1024];        public void setByteArray()
            {
                for (int i = 0; i < btTest.Length; i++)
                {
                    btTest[i] = (byte )i;            }
            }        public byte[] getByteArray()//返回值从 int 改为 byte[]
            {
                setByteArray();
                return btTest ;
            }        public void  fillBytes(byte[] btz)
            {
                try
                {
                    for (int i = 0; i < btz.Length; i++)
                    {
                        btz[i] = (byte)i;
                    }            }
                catch { }
             // return btz ;
            }
        }
    }delphi 端 调用代码:unit Unit10;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,     activex, { Variants,}
      DB, ADODB,Grids, DBGrids, DBClient, StdCtrls, Provider,
      frmByteArrayToDelphi_TLB,  Dialogs;type
      TForm10 = class(TForm)
        Button1: TButton;
        DBGrid1: TDBGrid;
        Edit1: TEdit;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;    type
        mybuffer=array [0..1023] of byte;
    var
      Form10: TForm10;implementation{$R *.dfm}procedure TForm10.Button1Click(Sender: TObject);
    var
    ttest:Interface1;
    mybf:mybuffer;
    dp:pointer;
    buf3:psafearray;
    Arr: Variant;
    i:Integer;
    begin
    buf3:=allocmem(1024);    //申请psafearray内存
    zeromemory(buf3,1024);   //清空内存
    zeromemory(@mybf[0],1024); //清空数组ttest:=CoForm1.Create() AS INTERFACE1;   //创建接口实例
    buf3:=  ttest.getByteArray ; //正常返回(调用 接口实例,返回psafearray 指针);CopyMemory(@mybf[0],buf3.pvData ,1024); //从psafearray指针 copy数据到 mybuffer
     //CopyMemory(@mybf[0],buf3.pvData ,1024); //从psafearray指针 copy数据到 mybufferend;end.
    C#dll的编写 参见0楼附注
    谢谢各位顶友。
    接分啦。