2013-04-24 43 views
2

這是調用代碼我用Delphi調用DLL,但仍然有一個錯誤

unit CY; 

interface 
uses windows; 
type 

TMember_Rd = Record 
    iID: integer; 
    sCode: Array[0..255] of char; 
    sName: Array[0..255] of char; 
    end; 

    PTMember_Rd = ^TMember_Rd; 

function GetMember(sStore, sMachine: PChar; const sTrack, sCode, sVerify: PChar; 
    Member: PTMember_Rd; sError: PChar): Integer; stdcall; external 'Interface.dll'; 

implementation 

end. 

我需要調用一個GetMember功能和數據填寫到會員,如果有任何錯誤我可以從sError獲取消息。

如何調用此函數?

我不熟悉德爾福;我認爲我的錯誤在於指針。

以下是我的C#代碼工作

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using System.Text; 

namespace JFTest 
{ 
    public class JFService 
    { 
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
     public struct PTMember_Rd 
     { 
      public Int32 id; 

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
      public string sCode; 

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
      public string sName; 
     } 

     [DllImport("Interface.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] 
     public static extern int GetMember(StringBuilder sStore, StringBuilder sMachine, StringBuilder sTrack, StringBuilder sCode, StringBuilder sVerify, ref PTMember_Rd Member, [MarshalAs(UnmanagedType.LPStr)] string sError); 

    } 
} 

而且我也沒有對方的代碼,該dll是客戶發給我,他們沒有源代碼。

+0

請顯示界面的另一邊。我認爲有一些C代碼。另外,請告訴我們Delphi的版本,以便我們判斷'Char'是一個字節寬還是兩個字節寬。 – 2013-04-24 16:19:25

+0

我只知道這個接口在其他程序中工作,並且sError會返回unicode,我使用delphi 2010開發它。謝謝大衛。 – user2316439 2013-04-24 16:24:26

+1

這是一個互操作問題。你有兩個不匹配的接口。如果你只顯示界面的一面,你不能指望我們回答。顯示另一面。還提供參數的文檔。對於指針參數,誰負責分配內存。輸入哪些參數,輸出哪些參數? – 2013-04-24 16:26:02

回答

1

我認爲你的p/invoke代碼是錯誤的。你說MembersError是輸出參數,其他參數是輸入的。在這種情況下的P/Invoke應該是:

[DllImport("Interface.dll", CharSet=CharSet.Ansi)] 
public static extern int GetMember(
    string sStore, 
    string sMachine, 
    string sTrack, 
    string sCode, 
    string sVerify, 
    ref PTMember_Rd Member, 
    StringBuilder sError 
); 

假設這是正確的,在Delphi應該是這樣的:

type 
    TMember_Rd = Record 
    iID: integer; 
    sCode: Array[0..255] of AnsiChar; 
    sName: Array[0..255] of AnsiChar; 
    end; 

function GetMember(
    sStore: PAnsiChar; 
    sMachine: PAnsiChar; 
    sTrack: PAnsiChar; 
    sCode: PAnsiChar; 
    sVerify: PAnsiChar; 
    out Member: TMember_Rd; 
    sError: PAnsiChar 
): Integer; stdcall; external 'Interface.dll'; 

其中sStoresMachine等是指定輸入參數字符串變量。

我們需要使用一個字節AnsiCharPAnsiChar。您的問題中的代碼使用兩個字節的UTF-16 CharPChar

你會這樣稱呼它:

var 
    sError: AnsiString; 
    Member: TMember_Rd; 
    retval: Integer; 
.... 
SetLength(sError, 256); 
retval := GetMember(
    PAnsiChar(AnsiString(sStore)), 
    PAnsiChar(AnsiString(sMachine)), 
    PAnsiChar(AnsiString(sTrack)), 
    PAnsiChar(AnsiString(sCode)), 
    PAnsiChar(AnsiString(sVerify)), 
    Member, 
    PAnsiChar(AnsiString(sError)) 
); 

我不知道sError字符串需要多大的空間來進行。如果你沒有任何文件,你無法找到。最好讓它變大並希望最好。如果不夠大,並且該函數試圖寫入該緩衝區,那麼您的緩衝區溢出。

我認爲Member參數具有純粹的語義,因爲這就是你所說的。如果您需要使用部分或全部字段傳遞數據,請將其更改爲var並相應地初始化記錄。

+0

@user你問了這個問題,得到了這個答案,然後安靜下來。你仍然對這個問題感興趣嗎?你還在堅持嗎?反饋會很好。 – 2013-04-26 06:40:19

相關問題