2012-03-23 201 views
4

在C#,我所定義的結構:轉換結構手柄從託管到非託管C++/CLI

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct MyObject 
{ 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string var1;  

    [MarshalAs(UnmanagedType.LPWStr)] 
    public string var2;  
}; 

我有這樣的結構在C++:

public value struct MyObject 
{ 
    LPWSTR var1;  
    LPWSTR var2;  
}; 

而在C的方法++這是從C#調用公共類:

TestingObject(MyObject^ configObject) 
{ 
    // convert configObject from managed to unmanaged. 
} 

對象調試正確,我可以看到兩個字符串var1和var2。但是,現在的問題是,我需要將對象編號爲:configObject放入非託管對象中。

我想到的是做這樣的事情:

TestingObject(MyObject^ configObject) 
{ 
    // convert configObject from managed to unmanaged. 
    MyObject unmanagedObj = (MyObject)Marshal::PtrToStructure(configObject, MyObject); 
} 

這是我能想到的不過關過程中,我得到這個錯誤:

Error 2 error C2275: 'MyObject' : illegal use of this type as an expression

是轉換是正確的託管對象變爲非託管對象?如果是這樣,那麼我怎樣才能正確地確定Marshal::PtrToStructure?如果不是,我該怎麼辦?

+0

除非您定義名爲'LPWSTR'的別名(或實際類型),否則您的C#將不會編譯。 – svick 2012-03-23 16:14:37

+0

這是我的錯誤。我只是更新了它 – olidev 2012-03-23 16:16:04

+0

像他的回答中提到的@Botz一樣,這裏沒有非託管類型。你想做什麼? – 2012-03-23 16:18:57

回答

2

Marshal::PtrToStructure與您想要的相反,它將非託管指針轉換爲託管對象。你需要Marshal::StructureToPtr

另外,您需要定義一個非託管類,因爲MyObject是一個託管類型。假設你已經這樣做了,你可以做這樣的(只是轉換這從C#示例):

IntPtr pnt = Marshal::AllocHGlobal(Marshal::SizeOf(configObject)); 
Marshal.StructureToPtr(configObject, pnt, false); 

然後,您有一個指針數據,這些數據可以memcpy或任何到您的原生結構。

但是MyObject是和將保持託管類型。如果你想要一個真正的非託管類型,你必須定義一個與託管結構相匹配的類型。

只是想知道,爲什麼你在託管結構中使用非託管LPWSTR?

+0

我剛剛更新了我的問題,其中也包括C#中的對象,您可以看到我在C++中定義了相同的問題。你是對的,我複製託管對象configObject到pnt。但是我怎樣才能從那個pnt創建一個非託管的ConfigObject呢?提前致謝。 – olidev 2012-03-23 16:10:54

+0

這些類定義都是管理的。你爲什麼不在C++程序集中只定義類**,並使用C#中的類?我的意思是你已經引用了圖書館。然後你會使用同一個班級。 – Botz3000 2012-03-23 16:18:37

+0

我對這個主題沒有經驗,從C#發送一個結構到C++。所以你的意思是我需要先用C++來構造它,然後再使用C#。 C++中的結構定義應該是什麼?你能給我建議嗎?在此先感謝 – olidev 2012-03-25 19:51:14

1

你大概的意思是:

struct MyUnmanagedStruct { 
    LPWSTR var1, var2; 
}; 

然後你可以使用Marshal.StructureToPtr通過Botz3000的建議。否則,C#的

public struct MyObject { 
    public String var1; 
    public String var2; 
} 

和C++/CLI的

public struct value MyObject { 
    public String^ var1; 
    public String^ var2; 
} 

是完全等價的,假設your're你使用兩邊的相同System.String

+0

謝謝。因爲我問了另一個問題:http://stackoverflow.com/questions/9651585/how-to-set-an-object-into-c-from-c-sharp,他們建議使用LPWSTR。對於你的其他解決方案,我需要將String ^轉換爲C++中的字符串,對吧? – olidev 2012-03-25 19:49:33

+0

嗯,不,或者是...因爲我不確定你現在在做什麼。在另一個線程中,您詢問如何使.NET對象可用於native C++。是的,你得到的答案是一種可能的方式,儘管不是最優雅的,也不是最安全的。從你在這裏發佈的內容可以看出,當你試圖做一些奇怪的事情時:將未調整的字符串存儲在託管值類型「public value struct MyObject」中... – 2012-03-28 15:20:20