有關C#呼叫Delphi DLL傳遞Array of record型態的問題 |
答題得分者是:syntax
|
minjiu
中階會員 ![]() ![]() ![]() 發表:27 回覆:119 積分:69 註冊:2002-06-26 發送簡訊給我 |
以下是我測試的大概程式碼...
每次在C#呼叫Delphi的DLL函式都會出錯,請問各位高手,我這樣寫是否有錯,要如何修改,謝謝!! 以下是Delphi DLL的型態宣告: [code delphi] type TRecDetail = packed record DetailID : Integer; DetailNO : PAnsiChar; end; PRecDetailArray = ^TRecDetailArray; TRecDetailArray = array of TRecDetail; type TRecMain = packed record MainID : Integer; MainNO : PAnsiChar; Detail : PRecDetailArray; end; PRecMainArray = ^TRecMainArray; TRecMainArray = packed array of TRecMain; .... // 給C#呼叫的函式 procedure SendData(var Data : PRecMainArray); stdcall; begin ..... end; [/code] 以下是C#型態宣告: [code c#] public struct TRecDetail { public int DetailID; public String DetailNO; } public struct TRecMain { public int MainID; public String MainNo; public TRecDetail[] Detail; } // 外部DLL函式 [DllImport(DllFile)] public static extern void SendData(ref TRecMain[] RecMain); ... // 實際呼叫 private void button4_Click(object sender, EventArgs e) { int iMainCount = 5, iDetailCount = 3; int iCount = 0; TRecMain[] RecMain = new TRecMain[iMainCount]; for (int i = 0; i < iMainCount; i ) { RecMain[i].MainID = i; RecMain[i].MainNo = "M00" i.ToString(); RecMain[i].Detail = new TRecDetail[iDetailCount]; for (int j = 0; j < iDetailCount; j ) { iCount ; RecMain[i].Detail[j].DetailID = iCount; RecMain[i].Detail[j].DetailNO = "D00" iCount.ToString(); } } SendData(ref RecMain); } [/code] 編輯記錄
minjiu 重新編輯於 2010-03-24 19:44:33, 註解 無‧
minjiu 重新編輯於 2010-03-24 19:46:10, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:47:16, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:53:47, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:54:06, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:54:35, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:56:00, 註解 無‧ minjiu 重新編輯於 2010-03-24 19:57:30, 註解 無‧ |
syntax
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
拿掉 packed
===================引 用 minjiu 文 章=================== 以下是我測試的大概程式碼... 每次在C#呼叫Delphi的DLL函式都會出錯,請問各位高手,我這樣寫是否有錯,要如何修改,謝謝!! 以下是Delphi DLL的型態宣告: [code delphi] type TRecDetail = packed record DetailID : Integer; DetailNO : PAnsiChar; end; PRecDetailArray = ^TRecDetailArray; TRecDetailArray = array of TRecDetail; type TRecMain = packed record MainID : Integer; MainNO : PAnsiChar; Detail : PRecDetailArray; end; PRecMainArray = ^TRecMainArray; TRecMainArray = packed array of TRecMain; .... // 給C#呼叫的函式 procedure SendData(var Data : PRecMainArray); stdcall; begin ..... end; [/code] 以下是C#型態宣告: [code c#] public struct TRecDetail { public int DetailID; public String DetailNO; } public struct TRecMain { public int MainID; public String MainNo; public TRecDetail[] Detail; } // 外部DLL函式 [DllImport(DllFile)] public static extern void SendData(ref TRecMain[] RecMain); ... // 實際呼叫 private void button4_Click(object sender, EventArgs e) { int iMainCount = 5, iDetailCount = 3; int iCount = 0; TRecMain[] RecMain = new TRecMain[iMainCount]; for (int i = 0; i < iMainCount; i ) { RecMain[i].MainID = i; RecMain[i].MainNo = "M00" i.ToString(); RecMain[i].Detail = new TRecDetail[iDetailCount]; for (int j = 0; j < iDetailCount; j ) { iCount ; RecMain[i].Detail[j].DetailID = iCount; RecMain[i].Detail[j].DetailNO = "D00" iCount.ToString(); } } SendData(ref RecMain); } [/code] |
minjiu
中階會員 ![]() ![]() ![]() 發表:27 回覆:119 積分:69 註冊:2002-06-26 發送簡訊給我 |
|
syntax
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
1. DLL 不應使用編譯器相依的程式碼, no packed, no dy array
2. 過於複雜的 結構,要 port 到 .Net 必須外加一層處理,即是將原來複雜結構的資料取出,另外組合成簡單結構 3. 觀念請看 http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx ===================引 用 minjiu 文 章=================== 感謝 syntax 的回答,可是我不管有沒有加上packed, 在C#執行到SendData(ref RecMain); 就會出現"參數錯誤。 (發生例外狀況於 HRESULT: 0x80070057 (E_INVALIDARG))"的錯誤訊息, 請問還有哪裡可能會有問題,謝謝!! |
minjiu
中階會員 ![]() ![]() ![]() 發表:27 回覆:119 積分:69 註冊:2002-06-26 發送簡訊給我 |
再次感謝syntax 的回答...
看來目前只能將 RecMain 裡的 RecDetail 拆開另外傳遞了,改成傳2個參數就沒問題了... 不過參數內容可正確的傳至Delphi DLL中後,在Delphi中確無法使用Length(), Low() 或 High()函式正確的 RecMain array 及 RecDetail array的大小,真是奇怪... [code delphi] type TRecDetail = packed record MainID : Integer;DetailID : Integer; DetailNO : PAnsiChar; end; PRecDetailArray = ^TRecDetailArray; TRecDetailArray = array of TRecDetail; type TRecMain = packed record MainID : Integer; MainNO : PAnsiChar; end; PRecMainArray = ^TRecMainArray; TRecMainArray = packed array of TRecMain; .... // 給C#呼叫的函式 procedure SendData(var PMain : PRecMainArray;var PDetail : PRecDetailArray); stdcall; var Main : TRecMainArray; Detail : TRecDetailArray; begin Main := PRecMainArray(PMain)^; Detail := PRecDetailArray(PDetail)^; Length(Main); >> 取出的大小不正確 (不管由C#傳過來的array大小為何,這裡取出來的值都固定不變) Length(Detail); >> 取出的大小不正確 (不管由C#傳過來的array大小為何,這裡取出來的值都固定不變) Main[0].MainID; >> 傳過來的值都正確 Main[0].MainNo; >> 傳過來的值都正確 Main[1].MainID; >> 傳過來的值都正確 Main[1].MainNo; >> 傳過來的值都正確 Main[2].MainID; >> 傳過來的值都正確 Main[2].MainNo; >> 傳過來的值都正確 Detail[0].DetailID; >> 傳過來的值都正確 Detail[0].DetailNo; >> 傳過來的值都正確 Detail[1].DetailID; >> 傳過來的值都正確 Detail[1].DetailNo; >> 傳過來的值都正確 Detail[2].DetailID; >> 傳過來的值都正確 Detail[2].DetailNo; >> 傳過來的值都正確 .... end; [/code] ===================引 用 syntax 文 章=================== 1. DLL 不應使用編譯器相依的程式碼, no packed, no dy array 2. 過於複雜的 結構,要 port 到 .Net 必須外加一層處理,即是將原來複雜結構的資料取出,另外組合成簡單結構 3. 觀念請看 http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx ===================引 用 minjiu 文 章=================== 感謝 syntax 的回答,可是我不管有沒有加上packed, 在C#執行到SendData(ref RecMain); 就會出現"參數錯誤。 (發生例外狀況於 HRESULT: 0x80070057 (E_INVALIDARG))"的錯誤訊息, 請問還有哪裡可能會有問題,謝謝!!
編輯記錄
minjiu 重新編輯於 2010-03-26 19:17:47, 註解 無‧
|
syntax
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
Delphi 的 Array 是 Delphi 自己的格式
所以當然 Length Low High 無法使用,這很正常 所以你還必須傳陣列長度,這是不可以偷懶的 ===================引 用 minjiu 文 章=================== 再次感謝syntax 的回答... 看來目前只能將 RecMain 裡的 RecDetail 拆開另外傳遞了,改成傳2個參數就沒問題了... 不過參數內容可正確的傳至Delphi DLL中後,在Delphi中確無法使用Length(), Low() 或 High()函式正確的RecMain array 及RecDetailarray的大小,真是奇怪... [code delphi] type TRecDetail = packed record MainID : Integer;DetailID : Integer; DetailNO : PAnsiChar; end; PRecDetailArray = ^TRecDetailArray; TRecDetailArray = array of TRecDetail; type TRecMain = packed record MainID : Integer; MainNO : PAnsiChar; end; PRecMainArray = ^TRecMainArray; TRecMainArray = packed array of TRecMain; .... // 給C#呼叫的函式 procedure SendData(var PMain : PRecMainArray;var PDetail : PRecDetailArray); stdcall; var Main : TRecMainArray; Detail : TRecDetailArray; begin Main := PRecMainArray(PMain)^; Detail := PRecDetailArray(PDetail)^; Length(Main); >> 取出的大小不正確 (不管由C#傳過來的array大小為何,這裡取出來的值都固定不變) Length(Detail); >> 取出的大小不正確 (不管由C#傳過來的array大小為何,這裡取出來的值都固定不變) Main[0].MainID; >> 傳過來的值都正確 Main[0].MainNo; >> 傳過來的值都正確 Main[1].MainID; >> 傳過來的值都正確 Main[1].MainNo; >> 傳過來的值都正確 Main[2].MainID; >> 傳過來的值都正確 Main[2].MainNo; >> 傳過來的值都正確 Detail[0].DetailID; >> 傳過來的值都正確 Detail[0].DetailNo; >> 傳過來的值都正確 Detail[1].DetailID; >> 傳過來的值都正確 Detail[1].DetailNo; >> 傳過來的值都正確 Detail[2].DetailID; >> 傳過來的值都正確 Detail[2].DetailNo; >> 傳過來的值都正確 .... end; [/code] ===================引 用 syntax 文 章=================== 1. DLL 不應使用編譯器相依的程式碼, no packed, no dy array 2. 過於複雜的 結構,要 port 到 .Net 必須外加一層處理,即是將原來複雜結構的資料取出,另外組合成簡單結構 3. 觀念請看 http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx ===================引 用 minjiu 文 章=================== 感謝 syntax 的回答,可是我不管有沒有加上packed, 在C#執行到SendData(ref RecMain); 就會出現"參數錯誤。 (發生例外狀況於 HRESULT: 0x80070057 (E_INVALIDARG))"的錯誤訊息, 請問還有哪裡可能會有問題,謝謝!! |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |