别人提供的delphi动态库,我要用vc调用,
但是库里的参数有 string 类型,不知道要怎么调用。问下delphi 7 string 的内存结构,看是否可以构造出 相同内存结构的 “string”传入。或者谁能告诉我 其他的调用办法?

解决方案 »

  1.   

    从书上摘抄的字符串可以分为三大类:短字符串(ShortString)、长字符串(AnsiString /LongString)、宽字符串
    (WideString)。
    ShortString 在内存中占用0..255 字节,也就是说,它被固定分配256 字节。其中第0 字节存储字符
    串的实际长度,因此,一个ShortString 类型的变量实际最多存储255 个字符;但是,即使实际存储的字
    符不到255 个,它仍然在内存中霸道地占据256 字节。所以为了避免浪费,Object Pascal 又提供了另一
    种方法来声明更短的ShortString 变量:String[MaxLength]。一个String[MaxLength]类型的ShortString 占
    据0..MaxLength 共MaxLength+1 个字节。当然MaxLength 必须小于256。
    String 等同于AnsiString,否则等同于ShortStringDelphi中的String 一般等同于C/C++里的AnsiString
    http://www.cnblogs.com/del/archive/2007/12/03/981563.html
      

  2.   

    这个可能真不行。能不能让那个人改一下,在dll中怎么能用string做参数,这本身就有问题,就如同在vc++中用CString做参数一样,为什么不用PChar?用string不知道会有什么隐式问题,到时候调试都困难。
      

  3.   

    没什么问题
    delphi7的string类型,就是一块连续的内存,其中前四个字节是引用计数4字节 再后面是长度4字节, 后面就是内容ansistring,一个字符占一个字节。
    传递时把地址传入即可
      

  4.   

    一般做成dll的输出函数了,参数不会使用string而是pchar了的吧?
      

  5.   

    用PAnsiChar吧
    用string不行的
      

  6.   

    理论上应该可以。我手头没有c++,所以没法测试。先从delphi中说起。
    delphi7的String结构如下  PStrRec = ^StrRec;
      StrRec = packed record
        refCnt: Longint;  //引用计数
        length: Longint;  //字符串长度
         PStr: Pointer; //指向实际字符串的指针。
      end;首先你先在c中声明一个类似的结构体,然后,你动态开辟一个这个结构体的内存,假设是PS
    设置其中的 refCnt 至少要大于2,但是别设置成$FFFFFFFF(常量字符串被设置成这个),
    填写length域为字符串长度,填写PStr域指向实际字符串的首地址。
    然后,将这个结构中的 PStr 作为参数传递给dll的String参数(注意,是PStr 域 ,不是这个结构体的首地址 PS)。
    估计这样能行。
    用完了,记得在c中释放相关内存,呵呵
      

  7.   

    哦,上面给的结构有错误,抱歉啊,重来。
    应该是这样:
      StrRec = packed record
        refCnt: Longint; //引用计数,4个字节
        length: Longint; //字符串长度,4个字节
        Str:array[0..length-1] of Char; //实际字符串,实际长度是length中的长度
      end;
    大概就是这样一个结构。你在c首先开辟一块内存,其长度是你原始字符串的长度+4+4
    以上面的格式将字符串放在Str中,并将refCnt结构填写大于2的数,将length填写为实际字符串长度。
    然后,将Str的地址作为参数传递。
    其实,也就是开辟一个字符串长度+8的内存,然后将前4个字节填入数字2,将紧接着的4个字节添如字符串长度,再在随后的地方,把字符串的内容复制过去,最后,跳过前面8个字节,把这个内存中的实际字符串的地址传给dll,呵呵
      

  8.   

    c/c++可以写成:typedef struct
    {
        int refCount;
        int lenght;
        TCHAR data[1];
    }dString, *LPDString;
      

  9.   

    在Delphi7中调试,感觉应该传送自内容开始的地址而不是从引用计数开始的地址
      

  10.   


    结构体是正确的.但Delphi真正用的string其实是个指针.而且是指向data部分的指针,也就是refCount,lenght都是在负偏移的位置.
    另外Delphi2009,2010,XE及其以后版本增加了一个CodePage的成员.表示字符串语言的编码.
      

  11.   

    我用的是Delphi2010.Delphi2009之前只要去掉CodePage和elemSize是一样的.
    procedure TForm1.Button1Click(Sender: TObject);
    type
      PStrRec = ^StrRec;
      StrRec = packed record
        codePage: Word; //语言,Delphi2009之前没有这个域
        elemSize: Word; //语言,每个元素(可以理解成字符)大小,Delphi2009之前没有这个域
        refCnt: Longint; //引用计数
        length: Longint;  //长度
        data : array[0..0] of Char; //数据,实际长度以length+1为准,最后有一个#0
      end;
    var
      s : string;
      p : Integer;
      pstr : PStrRec;
    begin
      s := '1000'; //如果是字符串常量的话引用计数为-1.
      s := s + 'a';//这次引用计数应该是1  p := Integer(s);//string本身是个指针,指向StrRec.data
      pstr := PStrRec(p - 12); //取到 StrRec 的地址
      ShowMessage(Format('语言:%d;元素大小:%d;引用计数:%d;字符串长度%d;字符串内容:"%s"',[pstr.codePage, pstr.elemSize, pstr.refCnt, pstr.length, PChar(@pstr.data)]));
    end;