有方法:
function Test.get_Param(out a : BOOL): HRESULT; stdcall;
begin
a := b;
Result := T_Result;
end;
现在a := b;
发生异常,发生访问冲突异常。
当然,我可以尝试抓住它。但我不想那样做......
那么有什么方法可以确定使用某种方式并跳过任务。像:
if (! now I know it will happening that Exception){
a := b; // so I can skip
}
Result := T_Result;
也许这很容易,但因为我不知道使用delphi,所以希望你的家伙可以帮助我。感谢。
UPDATE1:
b: Boolean;//Some friend need to know what is the b param type.
UPDATE2:
我尝试使用:
if b<> nil then Enabled := b;
但我无法构建它,它将显示:E2008不兼容的类型
UPDATE3:
我正在尝试调试它,当我调试时,在Local variables面板上显示:
a Inaccessible值
我使用.NET称之为。有元数据:
bool get_Param{ [param: In, MarshalAs(UnmanagedType.Bool)] [PreserveSig] set; }
实际上我并没有使用.NET访问它。我使用.NET访问DirectShow过滤器,directshow过滤器是当前方法(由delphi编写)
UPDATE4:
这是部分C#代码
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SuppressUnmanagedCodeSecurity, Guid("hidden")]
public interface IDCDSPFilterInterface{
bool get_Param{ [param: In, MarshalAs(UnmanagedType.Bool)] [PreserveSig] set; }
.. hidden other ..
}}
答案 0 :(得分:2)
我尝试使用:
if b<> nil then Enabled := b;
但我无法构建它,它将显示:E2008不兼容的类型
指针变量是Pascal的ABC。 http://en.wikipedia.org/wiki/Pascal_(programming_language)#Pointer_types
所以编写该检查的正确方法是
function Test.get_Param(out a : BOOL): HRESULT; stdcall;
var ptr: ^BOOL;
begin
ptr := @a;
if nil = ptr then ....
a := b;
Result := T_Result;
end;
这是你明确问题的基本问题。
现在,实际上检查无济于事。它只会保护你的nil / NULL指针,但这不是可能发生的事情。发生的事情可能是随机垃圾指针而不是nil。由于调用代码中的错误。
同样,您可以通过var ptr: Pointer {untyped}; ptr := @Self; if ptr = nil then ...
或if nil <> Self
或仅if Assigned(Self)
检查 - 但这只能保护您免受NIL指针的攻击,而不是来自RANDOM GARBAGE指针。
更多的是,我认为实际的垃圾不是指向变量a
的指针,而是指向Self
和b
的指针是TEST类的成员,因此真实声明是a := Self.b;
。
由于您使用stdcall
我认为您正在尝试使用非Delphi语言中的EXE创建DLL。很可能你在该客户端应用程序代码中对函数做了错误的定义。实际上,如果Test
是一个类,你就可以做出正确的声明。如果get_Param
是RECORD Test
的方法,或者如果它是Test
类的STATIC CLASS方法,则只能使其正确。因此,编写函数的正确方法如下
function Test.get_Param(out a : BOOL): HRESULT;
begin
a := b;
Result := T_Result;
end;
function DLL_get_Param(const TestObject: pointer; out a : BOOL): HRESULT; stdcall;
var MyTest: Test;
begin
pointer(MyTest) := TestObject;
Result := MyTest.DLL_get_Param(a);
end;
export DLL_get_Param;
阅读Delphi文档,您可以获取/放入DLL函数。
Integers
,floats
,pointers
,IInterface
。您无法传递DLL复合体并执行诸如stings,动态数组,对象实例之类的对象。由于您无法传递对象实例,因此无法传递Self
变量,也无法调用方法。
抓住它的一种非常昂贵的方式就像
{global} var TestInstances: TList;
type
TEST = class...
procedure AfterConstructon; override;
procedure BeforeConstructon; override;
....
procedure Test.AfterConstructon;
begin
inherited;
TestInstances.Add(Self); // single-thread assumption here
end;
procedure Test.BeforeConstructon;
begin
TestInstances.Remove(Self); // single-thread assumption here
inherited;
end;
function Test.get_Param(out a : BOOL): HRESULT; stdcall;
begin
if not ( TestInstances.IndexOf(Self) >= 0 {found!} ) // single-thread assumption here
then ... WTF ???
...
....
initialization
TestInstances := TList.Create;
finalization
TestInstances.Free;
end;
如果您的DLL可以被多线程应用程序使用,您还应该将标记的调用包装到http://docwiki.embarcadero.com/Libraries/XE2/en/System.SyncObjs.TCriticalSection
答案 1 :(得分:1)
互操作边界的两侧存在严重不匹配。您的Delphi函数与C#声明不匹配。
解决方案不是测试参数有效性。鉴于问题中的函数声明,您的Delphi代码是正确的。解决方案是使互操作边界的两侧匹配。在你展示互操作边界的两边之前,我不能告诉你更多。
答案 2 :(得分:1)
由于我无法看到你已经去死的地方b
,我将假设它是Test
的成员。
因此,有一个很大的可能性是您有Test
的无效实例,并且您发现访问冲突试图阅读b
以便将其分配给a
。例如,以下使用get_Param
会引发异常。
var
LTest: Test;
LA: Boolean;
begin
LTest := nil;
LTest.get_Param(LA);
end;
关键是你需要一个有效的Test实例才能使用它。 E.g。
var
LTest: Test;
LA: Boolean;
begin
LTest := Test.Create;
try
LTest.get_Param(LA);
finally
LTest.Free;
end;
end;