2012-05-27 39 views
3

如何將一個空指針(又名:void*或句柄)放入COM VARIANT-類型中。包裝類_variant_t將其錯誤地轉換爲布爾值。但我需要把它作爲指針,以便.NET的COM-Marshaller將它識別爲IntPtr如何將一個void *放入COM VARIANT中,以便通過COM-Interop將其作爲IntPtr編組爲.NET?

我讀過的其中一條線索是this one at MSDN Social。他們建議這樣一種解決方案:

VARIANTARG Arg; 
VariantInit(&Arg); 
V_VT(&Arg) = VT_INT; 
V_INT(&Arg) = (int)m_hWnd; 

這種解決方案的問題是,V_INT(構件intVal)是32 bit integer並迫使指針是32個的指針。換句話說:我無法傳輸64位指針。有沒有解決這個問題的方法?任何其他方式把它轉換爲64位整數?

我已經測試了一些代碼。因此,我使用.NET方法接收任何System.Object並顯示其值和類型。

public static void TakePtr(object ptr) 
{ 
    Console.WriteLine("Received a " + ptr.GetType() + " with value " + ptr); 
} 

VARIANTv.llVal = 0; v.byref = myPointer;充滿了兼容性,因此它應該被編譯總是正確關於32/64位指針。另外我需要設置變體類型,以便.NET將它映射到System.IntPtr而不需要鑄造。 (因爲對於真正的Assembly,我不能更改代碼,也不想包裝它,這會增加主要的複雜性。)。

  • .NET傳送一個System.IntPtr向後作爲VT_INT,其forewards MAPPS到System.Int32
  • VT_I8 mapps到System.Int64但不是System.IntPtr

那麼VARENUM標誌會指定System.IntPtr

回答

2

目前我發現了一個解決完整問題的臨時解決方案:爲了在調用方法時明確定義參數類型,我將使用替代調用機制。因此,我使用下面的方法,它幾乎包裝類型invoke方法的參數,但是另外檢查類型並相應地投射它們,以便System.IntPtr被識別,而不是System.Int32System.Int64

public static object InvokeMember(this Type type, object obj, String name, System.Reflection.BindingFlags invokeAttr, Type[] argTypes, object[] argValues) 
{ 
    if (argTypes.Length != argValues.Length) throw new InvalidOperationException("Mismatching count of types an parameters."); 
    for (int i = 0; i < argTypes.Length; i++) if (argTypes[i] == typeof(IntPtr)) argValues[i] = new IntPtr(Convert.ToInt64(argValues[i])); 
    return type.InvokeMember(name, invokeAttr, null, obj, argValues); 
} 

這種方法的一個呼叫可能看起來像:

typeof(ExampleLib.HelloNET).InvokeMember(
    null, 
    "TakePtr", 
    BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, 
    new Type[] { typeof(IntPtr) }, 
    new object[] { 42 }); 

最後這已經從COM用於傳遞指針變體,其被填充所述:v.llVal = 0; v.byref = myPointer; v.vt = VT_INT;

/解決:-)

5

這是不可能的,VARIANT是一種自動化類型。自動化不喜歡處理指向未知類型的指針,沒有安全的方法來解除引用它們。唯一支持的指針類型是IUnknown *和IDispatch *,接口指針。

最好你可以將它存儲爲一個VT_I8,它可以封裝很長時間。您可以將其轉換爲IntPtr。

+0

簡單地傳遞值是一個部分問題,現在應該解決。 (我已經爲我的問題添加了解決方案。)另一方面,.NET沒有將它識別爲'System.IntPtr' *而沒有投射*的問題仍然存在。 –

1

PVOID byref;變體的成員看起來很有幫助。但我不確定應該設置哪種類型以伴隨它。

您可以按照Hans的建議使用LONGLONG llVal,因爲即使是32位平臺也有IntPtr(Int64)的構造函數。應該工作,直到有人發明128位指針。

0

我有類似的問題。當一個64位指針被放入一個PVOID變量類型中時,它會被截斷/編組爲32位指針! 於是我使用了VT_I8變體類型,並將指針放入它的llVal成員中,一切都很順利。

0

我使用了VT_VOID和byref參數,幾乎沒有任何問題。幾乎是因爲在某些情況下,.NET引發了一個有關從本機到管理對象的錯誤轉換的MDA錯誤(InvalidVariant錯誤)

我無法檢查問題是否在byref爲0時,因爲它沒有總是出現。 :)

相關問題