Delphi CopyMemory vs C++ memcpy
" ОК " - так, кажется, не простой вопрос.
у меня есть пользовательская библиотека (которая не написана мной), написанная на C++. Эта библиотека выполняет некоторые сетевые связи, и я просто передаю ей некоторые данные в виде массива байтов и извлекаю из него массив байтов с другой стороны. Библиотека обрабатывает все сетевые материалы для меня, отправляя / получая данные на / от клиента / сервера.
так, например, я могу написать клиент и сервер. От клиента я создаю массив байтов, библиотека принимает массив байтов и отправляет его на сервер. Сервер, который я написал, использует ту же библиотеку для обратного, т. е. обрабатывает весь прием трафика и в конечном итоге передает обратно массив байтов.
библиотека определяет массив байтов как часть структуры следующим образом... (Я загружаю библиотеку статически в Delphi, не думаю, что это будет иметь значение, но я использую FastMM4 - это повлияет на модель обмена памятью между приложением и dll? Насколько я знаю, используя FastMM должен быть в порядке, также попробовали ShareMem безрезультатно)
struct content {
void *data;
int size;
}
в любом случае, от моего клиента я пытаюсь отправить "Привет"... общепринятая мудрость заключается в том, что данные массива байтов копируются в эту структуру с помощью memcpy...
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
на моем сервере я отвечаю "World". Поэтому сервер отвечает следующим образом...
char *data = "World";
memcpy((void *)content.data(), data, strlen(data)); // last parameter is length, ie 5
// network.sendreply(content);
от клиента C++, взаимодействующего с сервером C++, я получаю эти данные на сервере...
0x0035fdf6 "Hello" (or in Bytes... 72, 101, 108, 108, 111)
так после это эссе, Я думаю, что код сервера C++ правильный, потому что я могу правильно общаться, если я пишу клиента на C++... Но замена клиента C++ клиентом, написанным на Delphi, не работает. Я заменил memcpy на CopyMemory, который, как я думал, сделал то же самое, но каким-то образом мой массив байтов отличается к тому времени, когда он достигает сервера c++... Мой клиент Delphi делает следующее...
// 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'
таким образом, данные из клиента Delphi выглядят правильными, но данные, полученные на сервере неверный... Как-то "привет" ('72 101 108 108 111') становится
0x003efd96 "h,H" (or in Bytes 104, 19, 44, 2, 72)
Я подозреваю, что делаю что-то не так с CopyMemory...? Или у меня неправильный обмен памятью между exe и dll? Как узнать, какую модель памяти использует сетевая библиотека C++? Или я просто скопировал этот массив байтов неправильно? Любая помощь очень ценится...
1 ответов
CopyMemory(lContentPointer, @ByteArray, 5);
ошибка в том, что ByteArray
является, по сути, указателем на первый элемент массива. Таким образом, вы передаете адрес указателя на первый элемент массива. Другими словами, у вас есть дополнительный, поддельный уровень косвенности. Вам нужно
CopyMemory(lContentPointer, @ByteArray[0], 5);
или
CopyMemory(lContentPointer, Pointer(ByteArray), 5);
как CopyMemory
vs memcpy
, первый является функцией Win32 API, а последний-стандартной библиотечной функцией C. Эти две функции выполняют идентичные задачи и сменный.