繁体   English   中英

尝试从VS2013 C#程序调用DELPHI XE2 DLL时出错

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM