Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当作为函数参数从Delphi传递到C#时,空字符串变为null_C#_Delphi_Com Interop - Fatal编程技术网

当作为函数参数从Delphi传递到C#时,空字符串变为null

当作为函数参数从Delphi传递到C#时,空字符串变为null,c#,delphi,com-interop,C#,Delphi,Com Interop,我有一个本地Delphi exe,它通过COM互操作调用C#dll。下面是演示此问题的最简单案例: 德尔菲: IClass1 = interface(IDispatch) ['{B29BAF13-E9E4-33D7-9C92-FE28416C662D}'] function Test(const aStr: WideString): WideString; safecall; end; var obj: IClass1; s: string; begin obj := Co

我有一个本地Delphi exe,它通过COM互操作调用C#dll。下面是演示此问题的最简单案例:

德尔菲:

IClass1 = interface(IDispatch)
  ['{B29BAF13-E9E4-33D7-9C92-FE28416C662D}']
  function Test(const aStr: WideString): WideString; safecall;
end;

var
  obj: IClass1;
  s: string;
begin
  obj := CoClass1.Create as IClass1;
  s := obj.Test('');  // Returns '[null]'
end;
C#:

当我在Delphi中使用空字符串调用方法Test时,C#部分接收null作为参数值。为什么呢?它不应该也是空字符串吗?

在Delphi中,null(即
nil
)和空字符串被视为等价的。因此,传递字符串的
'
(或
WideString
)参数在内部传递
nil
-

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

procedure Foo(const S: WideString);
begin
  WriteLn(Pointer(S) = nil);
end;

begin
  Foo('Something');  //FALSE
  Foo('');  //TRUE
  ReadLn;
end.

空字符串和空字符串的等式实际上是从COM。。。因此,COM库并不是真正坚持两者之间C风格区别的地方。

在Delphi中,
AnsiString
UnicodeString
,和
WideString
值在为空时由
nil
指针表示。COM对字符串使用
BSTR
。Delphi将
BSTR
包装为
WideString
。因此,无法将“空”非零字符串传递给以
WideString
作为参数的COM方法,而是
nil

为什么将
'
传递给
WideString
参数会导致另一方接收
null
?这就是Delphi表示空COM
BSTR
的方式。如果确实需要传递空字符串,则需要将Delphi代码中的
IClass1
更改为传递
TBStr
,而不是
WideString
,并使用
SysAllocString
SysAllocStringLen
创建空的
TBStr

将Delphi代码中函数的声明更改为:

function Test(const aStr: TBStr): WideString; safecall;
并在需要传递空字符串时传递
SysAllocStringLen(“”,0)

下面是一个完整的演示:

C#

Delphi

uses
  Ole2;

type
  IClass1 = interface(System.IDispatch)
    function Test(const aStr: TBStr): WideString; safecall;
  end;

var
  EmptyBStr: TBStr;

procedure Foo(const intf: IClass1); stdcall;
begin
  Writeln(intf.Test(nil));
  Writeln(intf.Test(EmptyBStr));
  Writeln(intf.Test(SysAllocString('foo')));
end;

exports
  Foo;

begin
  EmptyBStr := SysAllocStringLen('', 0);
end.
输出

[null] [empty] Not empty: foo [零] [空] 不是空的:foo
为了避免空指针的错误,您可以发送一个带有Chr(#0)或AnsiChar(#0)的空字符,而不是返回空指针的“”。
BSTR
可以为NULL,也可以为0长度的非NULL。这是Delphi,它没有区别。@ ReMyLeBeAu-当然,它可以在技术上被赋予许多COM约定,而不在(C++)中获得编译器支持。然而,代码应该(或至少应该)将null和零长度
BSTR
视为等价物(请参见)是的,但正如我在回答中指出的,您并没有被迫使用WideString。我已经用接口声明更新了我的问题。我没有首先添加它,因为它是从类型库自动生成的。@Max谢谢。我的最新更新向您展示了如何传递空字符串。
uses
  Ole2;

type
  IClass1 = interface(System.IDispatch)
    function Test(const aStr: TBStr): WideString; safecall;
  end;

var
  EmptyBStr: TBStr;

procedure Foo(const intf: IClass1); stdcall;
begin
  Writeln(intf.Test(nil));
  Writeln(intf.Test(EmptyBStr));
  Writeln(intf.Test(SysAllocString('foo')));
end;

exports
  Foo;

begin
  EmptyBStr := SysAllocStringLen('', 0);
end.
[null] [empty] Not empty: foo