2011-12-29 13 views
8

OK - Quindi non ho mai una domanda semplice.Delphi CopyMemory vs C++ memcpy

Ho una libreria personalizzata (che non è stata scritta da me) scritta in C++. Questa libreria fa alcune comunicazioni di rete e io passo alcuni dati ad esso come un array di byte e recupero un array di byte da esso sull'altro lato. La libreria gestisce tutte le risorse di rete per me l'invio/ricezione di dati da/a client/server.

Ad esempio, posso scrivere un client e un server. Dal client produco un array di byte, la libreria prende l'array di byte e lo invia a un server. Il server che ho scritto usa la stessa libreria per fare il contrario, cioè gestire tutta la ricezione del traffico e infine restituire un array di byte.

La libreria definisce l'array di byte come parte di una struct come segue ... (Sto caricando la libreria staticamente in Delphi, non penso che farà la differenza, ma sto usando FastMM4 - è questo andando ad incidere il modello di condivisione memoria tra app e dll? per quanto ne sono a conoscenza utilizzando FastMM dovrebbe essere OK, hanno anche cercato ShareMem inutilmente)

struct content { 
    void *data; 
    int size; 
} 

in ogni caso, dal mio cliente sto tentando di inviare " Ciao "... la saggezza accettata è che i dati dell'array di byte vengono copiati in questa struttura usando memcpy in questo modo ...

char *data = "Hello"; 
memcpy((void *)content.data(), data, strlen(data)); // last parameter is length, ie 5 
// network.sendrequest(content); 
// where content.data() returns the aforementioned pointer 

Sul mio server, rispondo con "World". Quindi il server risponde come segue ...

char *data = "World"; 
memcpy((void *)content.data(), data, strlen(data)); // last parameter is length, ie 5 
// network.sendreply(content); 

Da un C++ client comunica con un C++ Server ricevo questi dati sul server ...

0x0035fdf6 "Hello" (or in Bytes... 72, 101, 108, 108, 111) 

Così, dopo quel saggio, penso che il Il codice server C++ è corretto perché posso comunicare correttamente se scrivo un client in C++ ... Ma la sostituzione del client C++ con un client scritto in Delphi non funziona. Ho sostituito memcpy con CopyMemory, che ho pensato fatto la stessa cosa ma in qualche modo il mio array di byte è diverso dal momento in cui raggiunge il server C++ ... Il mio cliente Delphi fa la seguente ...

// lDataPointer is a retrieved reference to the 
// pointer (void *data; see above) defined in the 
// C++ library. It appears to be a valid pointer at runtime... 
lContentPointer := content.data(); // from DLL 
// Where ByteArray is populated with byte data of "Hello" 
CopyMemory(lContentPointer, @ByteArray, 5); // Copy from Exe to DLL 
// network.sendrequest(lContentPointer); 

// I have printed the byte array before the CopyMemory to check 
// its contents before sending, which is '72 101 108 108 111' 

Così i dati dal client Delphi sembra corretto, ma i dati ricevuti sul server non è corretto ... in qualche modo "Ciao" ('72 101 108 108 111') diventa

0x003efd96 "h,H" (or in Bytes 104, 19, 44, 2, 72) 

ho il sospetto che sto facendo qualcosa di sbagliato con CopyMemory ...? O ho sbagliato la condivisione della memoria tra exe e dll? Come faccio a sapere che tipo di memoria utilizza la libreria di rete C++? O ho appena copiato questo array di byte in modo errato? Qualsiasi aiuto molto apprezzato ...

+1

Penso che potresti essere frainteso qualcosa sulle DLL. Non esiste un "modello di condivisione della memoria" tra un EXE e una DLL - vengono eseguiti nello stesso spazio degli indirizzi. È possibile passare i puntatori avanti e indietro e l'EXE o la DLL possono leggerli/scriverli senza restrizioni. Tuttavia una particolare DLL potrebbe richiedere la copia dei parametri a seconda della sua specifica interfaccia. Nel tuo caso, chi assegna lo spazio per 'content.data'? Stai forse copiando i tuoi dati in uno spazio casuale determinato da un puntatore non inizializzato? –

+1

provare CopyMemory (lContentPointer, @ByteArray [0], 5); – ComputerSaysNo

+0

Penso che ti sia dimenticato di copiare * l'ultimo byte zero * nelle stringhe C. Per esempio. memcpy ((void *) content.data(), data, strlen (data) +1); La convenzione di stringa C è che le stringhe devono essere terminate da un byte zero. Pascal (e forse Delphi, non lo so) potrebbe avere una convenzione diversa (ad esempio l'avvio di stringhe con una parola che desse la loro lunghezza). Non riesco a rispondere alla tua domanda relativa a 'CopyMemory'. –

risposta

12
CopyMemory(lContentPointer, @ByteArray, 5); 

L'errore è che ByteArray è, di fatto, un puntatore al primo elemento della matrice. In questo modo si passa l'indirizzo del puntatore al primo elemento dell'array. In altre parole, hai un livello di riferimento indiretto extra spurio.È necessario

CopyMemory(lContentPointer, @ByteArray[0], 5); 

o

CopyMemory(lContentPointer, Pointer(ByteArray), 5); 

Per quanto riguarda CopyMemory vs memcpy, il primo è una funzione API Win32 e il secondo è una funzione di libreria C standard. Le due funzioni svolgono compiti identici e sono intercambiabili.

+0

Grazie David ... Pensa che due volte in due settimane hai risposto ai miei post ... – 0909EM

+0

@ 0909EM sì, è l'esperto di Delphi attivo qui intorno, +1 –

+0

@Seth Uno dei tanti che intendi ;-) –