2013-12-16 1 views
1

C# VS2013 프로그램의 Pinvoke를 사용하여 기존 DelphiXE2 DLL 프로그램에 액세스하려고합니다. Delphi 프로그램은 XML 파일과 IB 데이터베이스 파일을 가져 와서 XML 파일에 따라 데이터베이스를 업데이트합니다. DelphiXE2 dll 프로그램이 다른 Delphi 프로그램에서 성공적으로 호출되고 있습니다. C#에서는 GETxml 프로그램을 호출하려고합니다. { "외부 구성 요소에서 예외가 발생했습니다."} 오류가 발생했습니다.VS2013 C# 프로그램에서 DELPHI XE2 DLL을 호출하는 중 오류가 발생했습니다.

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); 

델파이 프로그램을 기존 : (나는 열려있는 데이터베이스가이 DLL 함수에서 발생되지 않은 것으로 나타났습니다 사실은은 GetXML 호출하기 전에 호출 델파이 프로그램에서 발생하는 경우 확실하지.. 이 문제 여부 나는 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; 

끝에 다른 가 ('파일 이름'+ oFilename + '매개 변수를 찾을 수 없습니다.') 가 Exception.Create 인상 시작한다.; 끝; 끝;

+0

왜'int retval = 0; retval = GetXML (...); '? 확실히 당신은'int retval = GetXML (...); '을 의미합니다. –

+0

그래, 변경했다. 감사. –

답변

2

먼저 interop 경계의 양측에 걸친 불일치를 살펴 보겠습니다. 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/invoke는 불필요하게 복잡합니다. 나는 당신의 p/invoke를 다음과 같이 작성합니다.

[DllImport("MSA.dll", CharSet = CharSet.Unicode)] 
extern static int GetXML(string a, string b, bool c); 

CallingConvention.StdCall이 기본값입니다. 여기에 함수 이름을 반복하기 때문에 EntryPoint을 지정할 필요가 없습니다. 그리고 CharSet.Unicode을 지정한 이후로 MarshalAs 속성이 필요하지 않습니다.


더 큰 문제는 interop 경계를 넘어 네이티브 Delphi 예외를 throw한다는 것입니다.

외부 구성 요소가이 상호 운용성 경계를 넘어 예외를 던지는 예외

를 던졌다 절대 안되는 일입니다 :는 P/계층을 호출이 반대하고 말했다 이유입니다. 그만해. 오류 코드로 구식 오류를 처리해야합니다.

+0

OMGOSH IT WORKED! 데이빗 너는 최고야. 저를 가르치고 제가 무엇을하려고했는지 이해하도록 도와 주셔서 감사드립니다. interop 경계를 넘어서 예외적으로 나는 그 문제를 보았고 Delphi App의 관리자와 함께 가져와야합니다. –