Создание CByteArray из CPointer в Visual Works Smalltalk

#smalltalk #visualworks

#smalltalk #visualworks

Вопрос:

Некоторые функции C возвращаются aCPointer к a C struct . Это C struct известно.
Теперь я хочу поместить C struct в ByteArray . В основном скопируйте содержимое структуры в a ByteArray .
В GemStone / S это можно сделать с помощью:
CByteArray fromCPointer: aCPointer numBytes: 120.
«это создает aCByteArray с содержимым структуры, на которую ссылается CPointer (копирование только 120 байт)»

Есть ли что-то подобное в Visual Works? Я его еще не нашел. Можно было бы реплицировать структуру C на уровне Visual Works, но это только одна структура, и ее можно обрабатывать на низком уровне.

Ответ №1:

Есть только довольно уродливые #copyAt:to:size:startingAt: , которые вы можете отправить указателю. Вам нужно выделить ByteArray себя (убедитесь, что он достаточно большой).

 answer := ByteArray new: size.
pointer
        copyAt: 0
        to: answer
        size: size
        startingAt: 1.
  

Другой способ (ByteArray -> Указатель) будет выполнен с помощью #copyAt:from:size:startingAt: .

Этот метод работает для обоих ByteArray и UninterpretedBytes . Если вы хотите считывать данные из байтов, UninterpretedBytes это может быть более полезным, поскольку вы можете отправлять такие вещи, как #longAt: чтение a long из смещения.

Комментарии:

1. Неинтерпретированные байты очень удобны. Как бы то ни было, если структура C выглядит так: struct FileAttr {char * name; char * longname; uint32_t флаги; uint8_t тип; uint64_t размер; char * owner;} fileAttr; Я могу прочитать все значения выше, но не «владелец». aCPointer>> at: и aCPointer>>copyAt:to:size:startingAt: не получает значение «владелец». Что довольно странно, потому что я могу читать другие значения.

2. К «владельцу» можно получить доступ с помощью aCPointer по адресу: 8, где 8 = byteNumberWhereTheOwnerAddressStart / 4

3. вам определенно следует подумать о том, чтобы просто определить C-Struct в вашем ExternalInterface . Гораздо проще получить доступ к элементам в структуре через memberAt: , чем самостоятельно возиться со смещениями. Вы должны взглянуть DLLandCConnectGuide.pdf на doc папку вашей установки VisualWorks. Главы 2 и 3 должны охватывать проблему, которую вы пытаетесь решить.

Ответ №2:

Если aCPointer указывает на структуру символа *, например:

 struct Names 
{char * name;
char * longname;} name;
  

Затем:

 (aCPointer at: 0) copyCStringFromHeap. "answer [name]"
(aCPointer at: 1) copyCStringFromHeap. "answer [longname]"
  

Для структур с символом * это работает хорошо, не тестировалось с другими типами C.