2013-08-02 8 views
6

Sto sviluppando una DLL che deve essere letta da un programma C#. Idealmente, il file .dll dovrebbe ricevere qualsiasi struct definito in C# e fare qualcosa con esso. Quindi, inizialmente, il tipo e la dimensione della struttura sono sconosciuti per la DLL C. Sono stato in grado di passare la struttura attraverso la funzione C extern, ed è superata per essere ricevuta, ma c'è un modo per scoprire le dimensioni e le caratteristiche di questa struttura di ricezione? c'è un modo per iterare sui suoi membri?iterate su struttura c sconosciuta passata da C#

questa è la funzione C definita per la DLL

extern int __cdecl testCSharp(mystruct * Test){ 

//sizeof(Test) is 4, so it is ok 

for(int i=0;i < sizeof(Test) ; i++){ 

    char * value = (char*) Test; //This access the first element. 
    cout << value << endl; //Prints "some random string", so, it is received ok 
} 

return 1; 

}

Questo è il codice C#

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)] 
unsafe public struct myStruct{ 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public string value1; 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public string value2; 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public string value3; 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public string value4; 
}; 

[DllImport("SMKcomUploadDLL.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern int testCSharp(ref myStruct message); 

static void Main() 
{ 
    int result; 

    myStruct message = new myStruct(); 

    message.value1 = "Some randome string"; 
    message.value2 = "0"; 
    message.value3 = "olkujhikvb"; 
    message.value4 = "isabedfbfmlk"; 

    result = testCSharp(ref message); 
} 

Tutti i tipi sono stringa in C# ed è suppossed a Rimane così, quindi è l'unica cosa che so sulla struttura che verrà passata.

Qualche idea?

Grazie in anticipo

+0

Cosa intendete per * "dovrebbe ricevere qualsiasi struttura definita in C#" *? C++ e C# sono lingue tipizzate staticamente. Quindi ogni tipo è noto al momento della compilazione su entrambi i lati. Inoltre, le definizioni dei tipi su entrambi i lati dovrebbero essere coerenti, quindi il marshalling può essere fatto senza problemi. – Nawaz

+2

Non penso che l'operatore 'sizeof' faccia quello che pensi che faccia. 'sizeof (Test)' restituisce 4 perché la dimensione di un poiner è di 4 byte (su una macchina a 32 bit). Questo non significa che ci siano 4 elementi in Test ... – PoByBolek

+0

@PoByBolek - Non riuscivo a capire cosa stia facendo questo codice, perché non potevo immaginare questa "semplice" spiegazione. – SChepurin

risposta

2

Come li stai smistamento come ByValTStr con una lunghezza di 100, non sono sicuro che sarete in grado di lavorare qualsiasi più di quanto quello che già avete (cioè il primo elemento).

Dai tipi MSDN (here)

NET Framework ByValTStr comportano come stringhe stile C, a dimensione fissa all'interno di una struttura (ad esempio, char s [5])

Se si usasse la terminazione NULL di LPStr o LPWStr invece si sarebbe in grado di calcolare la loro durata.