2016-12-20 4 views
0

Ich muss native Strukturen aus verwalteten Klassen füllen. Folgende Technik (1. kopiere verwaltete Daten in ein verwaltetes Byte-Array, 2. benutze memcopy, um die native Struktur zu füllen), fand ich eine übliche Lösung dafür. Ich nehme an, der Grund, warum der folgende Code nicht funktioniert, ist, dass ich verwaltete Klassen nicht verwaltete Strukturen verwende. Klassen verwalten ist eine Voraussetzung in meinem Projekt. Kann ich diesen Code mit verwalteten Klassen arbeiten lassen oder muss ich zu verwalteten Strukturen wechseln?Kopieren von verwalteter Klasse in systemeigene Struktur

dies ist die C# verwaltete Klasse:

[StructLayout(LayoutKind.Sequential)] 
public class man_s 
    { 
    public man_s() 
    { 
     // (do something which i can't do in a struct!) 
    } 

    // should go into a one-byte native bool 
    [MarshalAs(UnmanagedType.I1)] 
    public bool flag1; 

    public Int32 a; 

    public Int32 b; 
    }; 

... die native CPP-Struktur:

struct nat_s 
    { 
    public: 
      bool flag1; 
      __int32 a; 
      __int32 b; 
    }; 

... der Code, der die verwalteten Daten in die native Struktur kopieren sollten:

// setup some managed data 
man_s^ mng = man_s(); 
    mng->flag1 = true; 
    mng->a = 10; 
    mng->b = 20; 

    nat_s nat; 
    int s = sizeof(nat); 

    // size check is ok! 
    System::Diagnostics::Debug::Assert(sizeof(nat) == System::Runtime::InteropServices::Marshal::SizeOf(mng)); 

    // copy into managed byte array 
    array<byte>^ byteArray = gcnew array<byte>(s); 
    System::Runtime::InteropServices::Marshal::Copy(IntPtr((void*)(&mng)), byteArray, 0, s); 

    // this doesn't bring up the expected results 
    pin_ptr<byte> start = &byteArray[0]; 
    memcpy(&nat, start, s); 

    // does not work either 
    System::Runtime::InteropServices::Marshal::Copy(byteArray, 0, IntPtr((void*)(&nat)), s);enter code here 

Antwort

0

Marshal.Copy ist zum Kopieren von Daten zwischen verwalteten Arrays und nicht verwalteten Arrays. Das haben Sie hier nicht: Sie haben ein verwaltetes Objekt und eine nicht gemachte Struktur. Dafür wollen Sie die Methoden PtrToStructure und StructureToPtr. Diese Methoden zielen auf das Kopieren zwischen einem verwalteten Objekt und einem nicht verwalteten Speicher ab.

// Despite the name, man_s is a managed class, not a managed struct. 
// This means it gets the^(which you had correct), 
// but it also means it gets gcnew (which you were missing). 
man_s^ mng = gcnew man_s(); 
nat_s nat; 

// You had this code is correct. 
Debug::Assert(sizeof(nat) == Marshal::SizeOf(mng)); 

// StructureToPtr copies to unmanaged memory. 
// An unmanaged array (i.e., allocated with `malloc` or `new byte[]`) 
// would work, but a pointer to the unmanaged struct will also work just fine. 
// The `false` means "Don't destroy the object that's already at the destination", 
// which I believe does not apply here. 
Marshal::StructureToPtr(mng, &nat, false); 

// You can go the other way as well. 
Marshal::PtrToStructure(&nat, mng); 
// or 
man_s = Marshal::PtrToStructure<man_s>(&nat); 

Anmerkung: Ich bin jetzt nicht zu einem Compiler. Möglicherweise müssen Sie &nat in eine IntPtr umwandeln.

+0

danke gute Wahl – deafjeff

0

Nein. AFAIK können Sie nicht tun. Sie wissen nichts über das Speicherlayout eines verwalteten ref class. Sie können einen inneren value type innerhalb der Klasse zuweisen. Sie können dies anheften und dies als ganzen Block kopieren.

Auch ich verstehe Ihren Code nicht. Sie kopieren einen verwalteten Speicher mit Marshal :: Copy. Und Sie tun dies beim Konvertieren einer verwalteten Klasse in einen nativen Zeiger. Dann kopierst du dies in den verwalteten Speicher und kopierst diesen verwalteten Speicher erneut in einen nativen Speicher! Warum überhaupt? Wenn Sie einen Pin-Zeiger haben, der als nativer Zeiger fungiert.

+0

Wie oben erwähnt, ich kopierte verwaltet zu nativen, ich lernte es wie folgt: zuerst, kopieren Sie in verwalteten Byte-Array, und dann das bytewise memcpy in die native Struktur. Das ist alles. Vielleicht ein Schritt zu viel. Ich werde es versuchen mit einem Schritt weniger mit einem Werttyp. Danke trotzdem! – deafjeff

+0

ah, der letzte Marshal :: Kopieren im Code kommentiert "funktioniert auch nicht" ist nur ein zweiter Versuch, die wissen, dass ich weiß, muss auch scheitern. – deafjeff

+0

..getestet, Sie benötigen 2 Schritte, da pin_ptr einen Standardtyp (Byte) benötigt, um einen memcpy zu erstellen. – deafjeff

Verwandte Themen