- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我不止一次建议人们使用 WideString
类型的返回值来实现互操作目的。
这个想法是 WideString
与 BSTR
相同。 。因为 BSTR
是在共享 COM 堆上分配的,所以在一个模块中分配并在不同模块中释放是没有问题的。这是因为各方都同意使用相同的堆,即 COM 堆。
但是,WideString
似乎不能用作互操作的函数返回值。
考虑以下 Delphi DLL。
library WideStringTest;
uses
ActiveX;
function TestWideString: WideString; stdcall;
begin
Result := 'TestWideString';
end;
function TestBSTR: TBstr; stdcall;
begin
Result := SysAllocString('TestBSTR');
end;
procedure TestWideStringOutParam(out str: WideString); stdcall;
begin
str := 'TestWideStringOutParam';
end;
exports
TestWideString, TestBSTR, TestWideStringOutParam;
begin
end.
以及以下 C++ 代码:
typedef BSTR (__stdcall *Func)();
typedef void (__stdcall *OutParam)(BSTR &pstr);
HMODULE lib = LoadLibrary(DLLNAME);
Func TestWideString = (Func) GetProcAddress(lib, "TestWideString");
Func TestBSTR = (Func) GetProcAddress(lib, "TestBSTR");
OutParam TestWideStringOutParam = (OutParam) GetProcAddress(lib,
"TestWideStringOutParam");
BSTR str = TestBSTR();
wprintf(L"%s\n", str);
SysFreeString(str);
str = NULL;
TestWideStringOutParam(str);
wprintf(L"%s\n", str);
SysFreeString(str);
str = NULL;
str = TestWideString();//fails here
wprintf(L"%s\n", str);
SysFreeString(str);
对 TestWideString
的调用失败并出现以下错误:
Unhandled exception at 0x772015de in BSTRtest.exe: 0xC0000005: Access violation reading location 0x00000000.
同样,如果我们尝试使用 p/invoke 从 C# 调用此函数,则会失败:
[DllImport(@"path\to\my\dll")]
[return: MarshalAs(UnmanagedType.BStr)]
static extern string TestWideString();
错误是:
An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in ConsoleApplication10.exe
Additional information: External component has thrown an exception.
通过 p/invoke 调用 TestWideString
可以按预期工作。
因此,使用 WideString 参数传递引用并将它们映射到 BSTR
似乎效果很好。但不适用于函数返回值。我已在 Delphi 5、2010 和 XE2 上对此进行了测试,并在所有版本上观察到相同的行为。
执行进入 Delphi 后几乎立即失败。对 Result
的赋值变成对 System._WStrAsg
的调用,其第一行内容如下:
CMP [EAX],EDX
现在,EAX
为 $00000000
,自然存在访问冲突。
有人能解释一下吗?难道我做错了什么?我期望 WideString
函数值是可行的 BSTR
是不合理的吗?或者这只是德尔福的缺陷?
最佳答案
在常规的 Delphi 函数中,函数返回实际上是通过引用传递的参数,尽管从语法上看它看起来和感觉起来都像“out”参数。您可以像这样测试它(这可能取决于版本):
function DoNothing: IInterface;
begin
if Assigned(Result) then
ShowMessage('result assigned before invocation')
else
ShowMessage('result NOT assigned before invocation');
end;
procedure TestParameterPassingMechanismOfFunctions;
var
X: IInterface;
begin
X := TInterfaceObject.Create;
X := DoNothing;
end;
演示调用TestParameterPassingMechanismOfFunctions()
由于 Delphi 和 C++ 对与函数结果传递机制相关的调用约定的理解不匹配,因此您的代码失败。在 C++ 中,函数返回的行为就像语法所示:一个 out
参数。但对于 Delphi 来说,它是一个 var
参数。
要修复,请尝试以下操作:
function TestWideString: WideString; stdcall;
begin
Pointer(Result) := nil;
Result := 'TestWideString';
end;
关于delphi - 为什么 WideString 不能用作互操作的函数返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9349530/
我想将虚拟键转换为 WideString。这就是我到目前为止所拥有的...... function VKeytoWideString (Key : Word) : WideString; var W
我有一个在 Windows 中显示气球托盘的函数,它的结构也是这样的: const NIF_INFO = $00000010; NIIF_NONE = $00
我有以下无法编译的代码片段: procedure Frob(const Grob: WideString); var s: WideString; begin s := Gr
我不止一次建议人们使用 WideString 类型的返回值来实现互操作目的。 Accessing Delphi DLL throwing ocasional exception ASP.NET web
我使用此过程将 key 枚举到 Delphi 7 中的 TNTListView (UNICODE) procedure TForm1.TntButton1Click(Sender: TObject);
我有一个文本,需要将其存储在 widestring 变量中。但我的文本是UTF8,而widestring不支持UTF8并将其转换为一些汉字。 WIDESTRING 有 UTF8 版本吗? 我总是使用U
我正在编写一个类,它将宽字符串保存到二进制文件中。我正在使用 Delphi 2005,但该应用程序稍后将移植到 Delphi 2010。我在这里感到非常不确定,有人可以确认一下吗: Delphi 20
该接口(interface)位于_TLB.pas文件 // *********************************************************************/
我正在尝试构建一个(测试)WideString: á (U+00E1 Small Letter Latin A with acute) 但是使用它的分解形式: LATIN SMALL LETTER A
德尔福有一个WrapText功能: function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; Max
如何将 PAnsiChar 变量转换为 WideString 或 string? 最佳答案 您只需将一个变量分配给另一个变量,然后让 Delphi 编译器为您完成所有转换: var p: PAns
在 C++Builder 中,我编写了以下代码(在 Button1Click 处理程序中),当我在 Debug模式下运行时,我得到“Int3 DbgBreakPoint”(堆栈已损坏?)。 AnsiS
(因为我还没有足够的声望来回答我自己的问题,所以我先把它放在这里。我发布它的时候没有想清楚。对我来说是凌晨 3 点,没有发生让我去别处寻找问题。 我正在创建另一个函数来在 lua 中动态添加一个对象,
我使用delphi 7。 我需要逐行读取一个utf-8文件,每行包含一个单词及其权重(一个数字)因此,我需要读取下一行,然后用分隔符(制表符)分隔行并将其保存在内存中。 所以, 1) Delphi 中
我有一个包含一些数据的 WideString 变量,但是当为字符串分配一些额外的空值时,这些空值或多或少地添加在数据中的随机位置。我现在需要从变量中去除这些空值。如果它是一个字符串,我会检查每个 Ch
我有非常旧的代码(来自 D3): TMyRecord = record Index : Integer; Header : String[70]; Strings : Array[
我有这个代码(我需要将字符串对象添加到 TStringList): var WS: WideString; begin WS := 'allocated string'; SL.AddOb
我很好奇这段代码在 Delphi 2010 中会发生什么: function foo: WideString; var myUnicodeString: UnicodeString; begin
我试图从用 Delphi 编写的 EXE 中接收信息。 EXE 向我传递了一个指向其数据结构之一的指针: Type RecordType = Record St: WideString
我有一种情况需要比较 char* 和 WideString。 如何在 C++ 中将 WideString 转换为 char*? 最佳答案 您可以使用 wcstombs 函数。 size_t wcsto
我是一名优秀的程序员,十分优秀!