2012-05-24 15 views
2

我用我自己的封送實現ICustomMarshaler與本機(非託管)DLL C函數工作。ICustomMarshaler :: MarshalNativeToManaged,接收來自本地的dll正確性「失去」的對象則返回

在功能MarshalNativeToManaged我看到從DLL側進入正確的結果。問題是,這MarshalNativeToManaged返回的對象不是「使用」。 (In,Out)參數調用函數中的對象不會更改。

(它看起來正是在previosly這裏討論同樣的問題,「C#:使用的PInvoke調用之後不包含數據的自定義編組對象」) C#: Object with custom marshaller not containing data after PInvoke call

的簡單類:

[StructLayout(LayoutKind.Sequential)] 
    class CMA { 
     public int a; 
     char b; 
     public char get_b() { return b; } 
    } 

函數的簽名如下所示:

[DllImport("first.dll", EntryPoint = "hack")] 
    public static extern int hack([In, Out, MarshalAs(UnmanagedType.CustomMarshaler, 
              MarshalTypeRef=typeof(ZMarshal))] CMA cma); 

某處主要我這樣稱呼它THI s:

int retcode = hack(cma); 

在MarshalNativeToManaged中,我確實看到了dll函數調用的正確結果。

public object MarshalNativeToManaged(IntPtr pNativeData) 
    { 
     // everything is fine with pNativeData; 
     // but let us even say I ignore it 
     // and return the object in the following way: 
     CMA cma = new CMA(); 
     cma.a = 999; 
     return cma; // this will be lost. I mean cma object in the main will not be changed 
    } 

我在做什麼錯在這裏? 只是一個快速注:我想知道如何使用CustomMarshaler不是「其他一些周圍的方式」來處理吧:)

回答

1

C#語言,您需要聲明一個參數作爲裁判允許它返回一個新的價值。修復:

[DllImport("first.dll", EntryPoint = "hack")] 
public static extern int hack(
    [In, Out] 
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ZMarshal))] 
    ref CMA cma); 
+0

非常感謝你的幫助。這是處理它的方法之一。我想我知道這裏發生了什麼,我已經回答了我自己的問題。當(如果)你有一些時間,請看看並添加一些評論/更正。 – AlexZJP

+0

嗯,不,全局變量*不是*處理它的方式。 –

+0

它不是全局的,它是類ZMarshal的成員變量。順便說一句,我們如何控制我們使用的封送處理器類的哪個實例? – AlexZJP

1

好吧,看起來我知道現在發生了什麼。竅門是,在處理Object時,我們真正處理指針(無論C#試圖隱藏這個事實有多困難)並且一步一步地執行:1)hack(CMA * pCMA); 2)MarshalManagedToNative(void * pCMA)// C#將我們傳遞給這裏的指針傳遞給這裏 3)void * _ MarsomeNativeToManaged(void * _some_PTR_to_memory_visible_to_managed_and_unmanaged_area) 這裏是QUESTION .NET用這個Void * ptr做了什麼,回報?如果不使用裁判有沒有辦法改變的黑客(CMA)的對象。這個指針根本不在任何地方使用。該功能可能是無效的。

public class ZMarshal : System.Runtime.InteropServices.ICustomMarshaler 
{ 
    static ZMarshal static_instance; 
    object oo; 
    public IntPtr MarshalManagedToNative(object o) 
    { 
     if (!(o is CMA)) 
      throw new System.Runtime.InteropServices.MarshalDirectiveException("Blabala"); 
     oo = o; 
在MarshalNativeToManaged

public object MarshalNativeToManaged(IntPtr pNativeData) 
    { 

     // some code that deals with the pNativeData really 
     // but for our example only let us say we simply ignore what we just got 
     // from the unmanaged world and simply change our object 

     ((CMA)oo).a = 999; 
     return oo; // this will not be lost now :) 

如果我們將使用參考這樣的黑客(REF CMA)

,後來; //由於以前的答案BTW 在這種情況下,它被破解(CMA ** PP)和.NET確實使用了我們從MarshalNativeToManaged *頁返回指針=∞;

底線是我們要麼保持我們的指針,並改變它指向的內存的價值,要麼(使用ref)傳遞指針指針(是的老好**真的),並改變指針的值本身。

相關問題