You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi向Go编译的C-Shared DLL传递字符串参数失败问题排查

问题:Go编译的C-Shared DLL在Delphi中无法正常传递字符串参数

我用Go编译了一个C-Shared格式的DLL,该DLL接收字符串作为参数,在Java、Python(使用ctypes模拟C字符串)中均可正常调用,但在Delphi中调用时无法正常传递字符串参数,以下是两种测试场景的细节:


1. Go函数接收string类型时的问题

Go代码

//export RequestCertificate
func RequestCertificate(jsonString string) *C.char{
    log.Println("String: ", jsonString)
    // 省略后续逻辑
}

Delphi代码

type 
  TGoString = record
    chars: PAnsiChar;
    length: LongInt;
  end;
jsonStr := payload.ToString;
jsonBytes := TEncoding.ANSI.GetBytes(jsonStr);
jsonB64 := TNetEncoding.Base64.Encode(jsonBytes);
goJson.chars := PAnsiChar(jsonB64);
goJson.length := Length(jsonB64);
response := RequestCertificate(goJson);

现象

Python通过模拟Go字符串结构体调用后,DLL输出符合预期;但Delphi调用后,DLL输出空字符串。


2. Go函数接收*C.char类型时的问题

Go代码

//export RequestCertificate
func RequestCertificate(CString *C.char) *C.char{
    log.Println("C String: ", CString)
    goString := C.GoString(CString)
    log.Println("GoString: ", goString)
    // 省略后续逻辑
}

现象

Python调用后DLL输出正常,但Delphi调用后,日志显示CString是内存地址,但转换后的goString为空。


问题原因分析

针对Go string类型的场景

Go的string结构体内存布局和你定义的TGoString不匹配:

  • Go的string由两个字段组成:指向字节数组的uintptr指针,以及表示长度的int类型。
  • 在Windows 64位环境下,uintptr和int都是64位(8字节),但你Delphi中的LongInt是32位(4字节),导致结构体整体大小错位。参数传递时Go端读取到错误的指针或长度值,最终得到空字符串。

针对*C.char类型的场景

主要可能是以下几个问题:

  1. 字符串缺少终止符:C风格字符串要求以\0空字符结尾,Go的C.GoString会读取到第一个\0为止。如果Delphi传递的字符串没有添加终止符,Go无法正确识别字符串内容。
  2. 位数不匹配:如果Go编译的DLL和Delphi程序位数不同(一个32位,一个64位),指针大小不一致,导致Go端接收到无效的内存地址,转换后的字符串为空。
  3. 内存分配问题:Delphi中直接将AnsiString转PAnsiChar时,若字符串被自动释放或内存地址无效,也会导致Go端读取失败。

解决建议

  1. 统一编译位数
    确保Go DLL和Delphi程序为同一位数:
  • 编译32位Go DLL:GOARCH=386 GOOS=windows go build -buildmode=c-shared -o your.dll
  • 编译64位Go DLL:使用默认GOARCH=amd64编译
  1. 修正Go字符串结构体定义
    如果要传递Go string,Delphi的结构体需匹配Go的内存布局:
type
  TGoString = record
    chars: UIntPtr; // 对应Go的uintptr
    length: Int64;  // 对应Go的int(64位)
  end;
  1. 确保C风格字符串带终止符
    传递*C.char时,手动分配带\0的内存:
var
  TempAnsiStr: AnsiString;
  CStr: PAnsiChar;
begin
  TempAnsiStr := jsonB64;
  CStr := StrAlloc(Length(TempAnsiStr) + 1);
  StrPCopy(CStr, TempAnsiStr);
  try
    response := RequestCertificate(CStr);
  finally
    StrDispose(CStr);
  end;
end;
  1. 验证编码一致性
    Base64编码后的字符串为纯ASCII,确认Delphi的字符串转换过程未丢失字节,避免编码差异导致的读取问题。

内容的提问来源于stack exchange,提问作者werick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:15:44