2009-08-25 68 views
1

另一個我的P/Invoke問題!我有這個C函數:通過引用傳遞結構引起AccessViolationException

int _ei_x_new(ei_x_buff* x); 

本質上,它初始化一個新的緩衝區結構。在C#中,我有這樣的:

[DllImport(EIDLL, EntryPoint = "_ei_x_new")] 
public static extern int ei_x_new(out ei_x_buff x); 

ei_x_buff很簡單:

typedef struct ei_x_buff_TAG { 
    char* buff; 
    int buffsz; 
    int index; 
} ei_x_buff; 

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct ei_x_buff { 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    public string buff; 
    public int buffsz; 
    public int index; 
} 

但是當我這樣做:

ei_x_buff buffer; 
Ei.ei_x_new(out buffer); 

我得到一個AccessViolationException

Att被迫讀取或寫入受保護的內存。這通常表明其他內存已損壞。

我需要分配一些內存還是什麼?這是一段簡單的代碼,我看不到任何明顯的問題。

編輯:母語爲_ei_x_new代碼:

// In my wrapper library 
DLL_EXPORT int _ei_x_new(ei_x_buff* x) { 
    return ei_x_new(x); 
} 

// In external library being wrapped 
int ei_x_extra = 100; 

int ei_x_new(ei_x_buff* x) 
{ 
    x->buff = malloc(ei_x_extra); 
    x->buffsz = ei_x_extra; 
    x->index = 0; 
    return x->buff != NULL ? 0 : -1; 
} 

回答

0

幾件事情

  • 使用了不REF中的PInvoke簽名,只要你想在兩個方向編組數據(流入和流出本機功能)
  • 您可以發佈本機簽名,因爲它們可能是定義的問題。特別的buff構件

EDIT

只是爲了消除一個可能性,開關的buff構件被鍵入的IntPtr與沒有屬性。如果這不會導致崩潰,那麼它可能是字符串類型的編組問題。

+0

P/Invoke簽名已用完。如果你的意思是「拒絕不出來」,它會產生相同的結果。本地簽名在問題中給出:int _ei_x_new(ei_x_buff * x); – 2009-08-25 03:33:39

+0

噢,你的意思是結構的本地簽名?我編輯了我的問題以顯示它。 – 2009-08-25 03:38:51

+0

將其更改爲IntPtr可以停止異常。我可以像這樣離開它,還是需要使用另一種類型? – 2009-08-25 03:44:36

0

做喲有緩衝區標記爲使用fixed聲明駐留在內存:

例如:

// assume class Point { public int x, y; } 
// pt is a managed variable, subject to garbage collection. 
Point pt = new Point(); 
// Using fixed allows the address of pt members to be 
// taken, and "pins" pt so it isn't relocated. 
fixed (int* p = &pt.x) 
{ 
    *p = 1; 
} 
+0

在這種情況下不應該是相關的 – JaredPar 2009-08-25 03:32:19

0

我認爲這將與字符串工作過,如果你只是initialisze緩衝區正確的C方。請記住,malloc返回的緩衝區可能包含垃圾,所以如果(x-> buff)x-> buff [0] ='\ 0',您應該添加如

;

您可能想要仔細檢查的另一件事是您在本地和託管端使用相同的調用約定。除非在DllImport屬性中指定了其他內容,否則CLR會採用_stdcall。