2011-03-04 68 views
4

我正在導入一些C++ dll到ac#項目中,我正在使用visual studio 2010.我已經成功導入了使用內置類型的函數,但是當我嘗試處理結構。這是一個簡單的例子:在c#項目中導入C++ dll

C++代碼

typedef long int TDate; 

typedef struct _TMDYDate 
{ 
    long month;       /* In range [1,12] */ 
    long day;       /* In range [1-31] */ 
    long year;       /* In range [1600-] */ 
} TMonthDayYear; 

int JpmcdsDateToMDY 
    (TDate date,      /* (I) TDate format */ 
    TMonthDayYear *mdyDate); 

,我已經翻譯成C#爲:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] 
public struct TMonthDayYear { 
    public int month; 
    public int day; 
    public int year; 
} 

public partial class NativeMethods { 

    [System.Runtime.InteropServices.DllImportAttribute("MyDll.dll", EntryPoint="JpmcdsDateToMDY")] 
public static extern int JpmcdsDateToMDY(int date, ref TMonthDayYear mdyDate) ; 

} 

,當我嘗試運行我的測試程序中的功能我得到這個錯誤:

未處理的異常:System.AccessViolationException:試圖讀取或寫入受保護的內存。這通常表明其他內存已損壞。在CsharpWrapper.NativeMethods.JpmcdsDateToMDY(的Int32日期,TMonthDayYear & MDY日期)

的結構是在棧中聲明,我認爲(也許)是問題,但我仍然得到,即使我有變化TMonthDayYear同樣的錯誤上課。

我在做什麼錯?

感謝您的幫助。

回答

3

您必須使用[DllImport]屬性中的CallingConvention屬性,因爲您沒有在本機函數聲明中使用__stdcall,所以這是Cdecl。雖然這是錯誤的,但它不是AV的很好解釋。你需要調試C代碼,AV表明它有一個指針錯誤。 Project + Properties,Debug,勾選「啓用非託管代碼調試」並在C函數上設置斷點。

坦率地說,像這樣的日期轉換應該用純C#編寫。

0

TDate本機代碼的類型是long int,但在託管代碼中它表示爲int32,而不是int64。

+0

你在說什麼?示例代碼中的提示器聲明瞭什麼類型爲「Int64」? – 2011-03-04 12:20:29

+0

@Cody Gray long int是Int64,而在代碼示例中,它被聲明爲int(Int32):native code:typedef long int TDate; int JpmcdsDateToMDY(TDate date,TMonthDayYear * mdyDate);我想知道如何使用C#中的靜態方法來實現這個功能。 – 2011-03-04 14:03:38

+0

@Darius:這確實是你的猜測(不是不合理的),但這是不正確的。第一個指出的是安東(「長螞蟻int具有相同的大小,所以結構的實現是正確的」),同一個人發佈這個答案。看看我爲什麼困惑? – 2011-03-04 14:57:46

0

它可能是也可能不是相關的,但你需要mdyDate參數上的[OutAttribute]才能寫入它。

0

如果你是一個習慣於C++的用戶,你可能很熟悉指針直接尋址內存。您的錯誤看起來像內存讀/寫保護相關的問題。

這是C#的標準性質所禁止的,您必須將編譯器置於Unsafe模式。

如果你在c#中不安全的代碼,你必須把代碼放到不安全的模式中。

unsafe 
    { 
    // unsafe things 
    } 

    unsafe class Class1 {} 

    static unsafe void someMethod (int* cpi, int lngth) {...} 

你還必須檢查的項目配置(構建 -Tab)和粘性的複選框「允許不安全的代碼」。

我很抱歉,如果我滾動一些太明顯的信息。我還會指出,如果情況是C#將解決內存問題,那麼此評論僅具有意義。