Delphi CopyMemory против C ++ memcpy

8

ОК - Поэтому у меня никогда не возникает простого вопроса.

У меня есть пользовательская библиотека (которая не написана мной), написанная на С++. Эта библиотека выполняет некоторые сетевые коммуникации, и я просто передаю им некоторые данные в виде байтового массива и извлекаю из него массив байтов с другой стороны. Библиотека обрабатывает все сетевые материалы для отправки/приема данных на/с клиента/сервера.

Так, например, я могу написать клиент и сервер. Из клиента я создаю массив байтов, библиотека принимает байтовый массив и отправляет его на сервер. Сервер, который я написал, использует одну и ту же библиотеку, чтобы сделать обратный, т.е. Обрабатывать весь прием трафика и в конечном итоге передавать массив байтов.

Библиотека определяет массив байтов как часть структуры следующим образом... (Я загружаю библиотеку статически в 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

На моем сервере я отвечаю "Мир". Таким образом, сервер отвечает следующим образом...

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

От клиента С++, взаимодействующего с сервером С++, я получаю эти данные на сервере...

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

Итак, после этого эссе, я думаю, что код сервера С++ верен, потому что я могу правильно общаться, если я пишу клиент на С++... Но замена клиента С++ клиентом, написанным в Delphi, не работает. Я заменил memcpy на CopyMemory, который, как я думал, сделал то же самое, но каким-то образом мой байтовый массив отличается к тому времени, когда он достигает сервера С++... Мой клиент 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 выглядят корректно, но данные, полученные на сервере, неверны... Как-то "Hello" ('72 101 108 108 111 ') становится

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

Я подозреваю, что я делаю что-то неправильно с CopyMemory...? Или мне не удалось обменять память между exe и dll? Как узнать, какую модель памяти использует сетевая библиотека С++? Или я просто скопировал этот массив байтов неправильно? Любая помощь очень ценится...

  • 1
    Я думаю, что вы можете неправильно понять что-то о DLL. Не существует «модели разделения памяти» между EXE и DLL - они работают в одном и том же адресном пространстве. Вы можете передавать указатели туда и обратно, и EXE или DLL могут читать / записывать их без ограничений. Однако конкретная DLL может потребовать от вас скопировать параметры в зависимости от его конкретного интерфейса. В вашем случае, кто выделяет место для content.data ? Возможно, вы копируете свои данные в случайное пространство, определяемое неинициализированным указателем?
  • 1
    попробуйте CopyMemory (lContentPointer, @ByteArray[0] [0], 5);
Показать ещё 3 комментария
Теги:
memory
bytearray

1 ответ

12
Лучший ответ
CopyMemory(lContentPointer, @ByteArray, 5);

Ошибка заключается в том, что ByteArray является, по сути, указателем на первый элемент массива. Таким образом, вы передаете адрес указателя на первый элемент массива. Другими словами, у вас есть дополнительный, ложный, уровень косвенности. Вам нужно

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

или

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

Что касается CopyMemory vs memcpy, первая функция Win32 API, а последняя является стандартной библиотечной функцией C. Обе функции выполняют идентичные задачи и взаимозаменяемы.

  • 0
    Спасибо, Дэвид ... Думаю, что дважды за две недели ты отвечал на мои сообщения ...
  • 0
    @0909EM 0909EM Да, он активный эксперт по Delphi, +1
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню