Delphi Firebird UDF只返回一个char

时间:2013-04-14 19:55:32

标签: delphi delphi-xe2 user-defined-functions firebird2.5

我正在使用Firebird 2.5。

我正在尝试编写一个Delphi XE2 UDF来从某些输入参数中返回一些字符串。

这是Delphi中的函数:

function  FormatRasaSingle(var formatRasa : PChar; var aDenumire : PChar; var aCod : PChar; var aSimbol : PChar; var aTulpina : PChar) : PChar;
var tmpString  : String;
    tmpInteger : Integer;
begin
  tmpString := formatRasa;
  tmpString := StringReplace(tmpString, '#DENUMIRE', aDenumire, [rfReplaceAll, rfIgnoreCase]);
  tmpString := StringReplace(tmpString, '#COD', aCod, [rfReplaceAll, rfIgnoreCase]);
  tmpString := StringReplace(tmpString, '#SIMBOL', aSimbol, [rfReplaceAll, rfIgnoreCase]);
  tmpString := StringReplace(tmpString, '#TULPINA', aTulpina, [rfReplaceAll, rfIgnoreCase]);
  tmpString := 'MAMA';
  tmpInteger := Length(tmpString) + 1;
  Result     := ib_util_malloc(tmpInteger);
  StrPCopy(Result, tmpString);
end;

udf声明是:

DECLARE EXTERNAL FUNCTION FORMATRASASINGLE
    CSTRING(255),
    CSTRING(255),
    CSTRING(255),
    CSTRING(255),
    CSTRING(255)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'FormatRasaSingle' MODULE_NAME 'eliteSoftFirebird';

当我试图测试函数结果时只有第一个字母“M”。

   tmpString := 'MAMA';

仅供测试。真正的代码就在这一行之前。

但无效。

有人可以建议我吗?

哪里出错?

此外,当我尝试输入一个参数时,我收到一个很大的错误,例如“从连接中读取数据时出错”。

Tks

勒兹


这个函数必须假设双参数是数字(5,2)?

function  FormatRasaMultiple(const formatRasa, aDenumire, aCod, aSimbol, aTulpina : PAnsiChar; aProcent : Double) : PAnsiChar; cdecl; export;

该函数与previos完全相同但是还有一个数字参数。

到目前为止(我的旧UDF Firebird 1.5)我使用声明为“var aProcent:Double”,但是当我返回时它没有任何价值。

UDF声明如下:

DECLARE EXTERNAL FUNCTION FORMATRASAMULTIPLE
    CSTRING(255),
    CSTRING(255),
    CSTRING(255),
    CSTRING(255),
    CSTRING(255),
    NUMERIC(5, 2)
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'FormatRasaMultiple' MODULE_NAME 'eliteSoftFirebird';

2 个答案:

答案 0 :(得分:1)

您选择了错误的数据类型jokers。

StringPCharChar不是Delphi中的数据类型,而是某些实际数据类型的别名。

取决于Delphi版本,有时在编译器设置上,这些可以是类型的快捷方式:

    Delphi 2009 +中的
  • UnicodeStringPWideCharWideChar
  • 默认情况下在Unicode前32位Delphi中:AnsiStringPAnsiCharAnsiChar
  • 在16位Delphi中或兼容性设置:ShortStringPAnsiCharAnsiChar

因此,在类型不安全的DLL项目中使用类型别名,您可以认为Delphi编译器会为您选择合适的数据类型。这次赌注失败了。

WideCharUnicodeString使用UTF-16字符集,对于非Unicode应用程序(或对于应用程序,通过协议期望非Unicode数据)看起来像零隔行扫描字符串(在pre中) -2009 Delphi条款)'a'^@'b'^@'c'^@而不是'abc'。根据ASCIIZ(C)字符串约定,这意味着字符串在第一个字符后结束。

因此,您应该在两侧使DLL接口匹配:您的源和Firebird期望。

  • 如果可能,您可以尝试说Firebird这些字段和结果使用UTF-16字符集,但我怀疑Firebird是否支持CSTRING
  • 您可以使用数据类型AnsiStringPAnsiCharAnsiChar
  • 根据Firebird DLL预期对您的DLL进行编码

我还强烈建议您阅读Delphi 2009+中关于Unicode的Delphi帮助及其对兼容性的影响,特别是对DLL和指针数学等低级类型不安全的东西。 Google中的主题文章也很少。

使用DLL删除Delphi编译器的类型安全检查,因此您负责确保DLL APi两侧的相同二进制数据表示。键入stringcharPChar等别名会使其非常脆弱且容易出错。


此外,我无法看到您为DLL入口点函数选择的调用约定。您是否使用cdecl关键字或stdcallregister标记了自己的功能? 根据{{​​1}} cdecl约定判断最可能是正确的,但您应该查看关于此主题的Firebird手册。

http://en.wikipedia.org/wiki/Calling_convention#x86

这适用于32位代码,但对于64位UDF,可能会要求另外一种约定。


现在,更奇怪的是你选择的参数模式。 您的函数具有c:\Program Files (x86)\Firebird\Firebird_2_1\include\ib_util.pas等参数,这意味着双重间接。 你的函数需要指针 - >指针 - >性格,这似乎不正确或理性。 我在函数参数定义中将var xxx:pointer限定符更改为var

这个样本 - 虽然它被抛弃并且质量有问题(它受到上面提到的头晕别名问题的困扰)也支持const限定符在这里错误的想法:http://fireudflib.cvs.sourceforge.net/viewvc/fireudflib/src/EMail.pas?view=markup


将这些点组合在一起,我想你的功能看起来应该是

VAR

http://docwiki.embarcadero.com/Libraries/XE3/en/System.SysUtils.StrPLCopy

答案 1 :(得分:0)

AFAIR,CSTRING表示空终止的类C字符串,因此您不能使用与UTF16相关的数据类型。请尝试使用ANSI类型。