[英]Error in trying to call a DELPHI XE2 DLL from VS2013 C# program
我正在尝试使用C#VS2013程序中的Pinvoke访问现有的DelphiXE2 dll程序。 Delphi程序获取一个xml文件和一个IB数据库文件,并根据xmlfile更新数据库。 已成功从另一个Delphi程序调用了DelphiXE2 dll程序。 在C#中,我试图调用GETxml程序。 我收到{“外部组件引发异常。”}错误。
由于我是C#和DELPHI的新手,因此需要对要执行的操作进行语法检查。
C#
[DllImport("MSA.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, EntryPoint = "GetXML")]
extern static int GetXML([MarshalAs(UnmanagedType.LPStr)] string a, [MarshalAs(UnmanagedType.LPStr)] string b, Boolean c);
int retval = 0;
retval = GetXML(txtPath.Text.ToString().Trim(), txtCabFile.Text.ToString().Trim(), false);
现有的Delphi程序:(我注意到该dll函数中没有发生数据库打开操作。实际上,它是在调用GetXML之前的调用Delphi程序中发生的。由于我是从C#调用的,所以不确定这是否是问题。程序。)
function GetXML(DatabasePath: pChar; OFileName: pChar; Silent: Boolean = True): Integer; stdcall;
var
xmlDatabase: TIBDatabase;
xmlTransaction: TIBTransaction;
objXML: TXML;
begin
Result := -1;
if FileExists(oFilename) then
begin
objXML := nil;
xmlDatabase := nil;
try
xmlDatabase := TIBDatabase.Create(nil);
xmlTransaction := TIBTransaction.Create(xmlDatabase);
xmlTransaction.DefaultDatabase := xmlDatabase;
xmlDatabase.DatabaseName := DatabasePath;
xmlDatabase.Params.Add('user_name=SYSTASS');
xmlDatabase.Params.Add('password=pswdf88');
xmlDatabase.LoginPrompt := False;
xmlDatabase.DefaultTransaction := xmlTransaction;
xmlDatabase.Connected := True;
xmlTransaction.StartTransaction;
try
objXML := TXML.Create(XMLDatabase, IsSecGDB(XMLDatabase)); //uses IBQUERY to start transaction
objXML.XMLIntoDB(oFilename, Silent);
xmlTransaction.Commit;
result := 1;
except
on e: Exception do
begin
xmlTransaction.Rollback;
raise Exception.Create('GetXML Exception: ' + e.Message);
end;
end;
finally
FreeAndNil(objXML);
if xmlDatabase <> nil then
xmlDatabase.Close;
FreeAndNil(xmlDatabase);
end;
结束否则开始引发Exception.Create('Filename'+ oFilename +'参数未找到。'); 结束; 结束;
首先,让我们看一下互操作边界两侧的不匹配。 您正在从C#传递ANSI字符串,但Delphi代码要求使用UTF-16。
[DllImport("MSA.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode, EntryPoint = "GetXML")]
extern static int GetXML(
[MarshalAs(UnmanagedType.LPStr)]
string a,
[MarshalAs(UnmanagedType.LPStr)]
string b,
Boolean c
);
尽管您指定了CharSet.Unicode
您随后继续使用UnmanagedType.LPStr
告诉编组器将其编组为PAnsiChar
。 对于UTF-16,您将使用UnmanagedType.LPWStr
但是,您的p /调用不必要地复杂。 我会这样写你的p /调用:
[DllImport("MSA.dll", CharSet = CharSet.Unicode)]
extern static int GetXML(string a, string b, bool c);
请注意, CallingConvention.StdCall
是默认设置。 此处无需重复指定EntryPoint
,因为它只是重复函数名称。 并且由于指定了CharSet.Unicode
因此不需要MarshalAs
属性。
现在,您面临的一个更大的问题是您在互操作边界上引发了本机Delphi异常。 因此,p / invoke层表示反对:
外部组件引发的异常
跨此互操作边界抛出异常是绝对不可以的。 别那样做。 您必须使用错误代码以传统方式处理错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.