char * теряется при возврате из C DLL в js-ctypes

Я работаю над расширением Thunderbird, которое будет вызывать существующий код C # через посредника C ++ / CLR. Я столкнулся с проблемой, которую можно воспроизвести, используя только C ++ / CLR DLL, или прямую C DLL.

Моя функция

 __declspec(dllexport)char* strTest2()
{
char *p = "Hello World";
char buffer[200];
char *q = buffer;

strcpy_s(q,200,p);

return p;
}

Если я верну p, я получу «Hello World» обратно. Если я возвращаю q, я получаю мусор или зависание. Проверка p и q в отладчике показывает, что они оба содержат одинаковые данные.

Я вызываю функцию, используя эту JS;

 Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("<path to DLL>");

var getStr = lib.declare("strTest2",
ctypes.default_abi,
ctypes.char.ptr);

var str = getStr();
alert(str.readStringReplaceMalformed());

lib.close();

В отладчике Mozilla str идентифицируется как объект типа CData, и копание достаточно далеко показывает, что в каждом случае он содержит строку, хотя я не могу увидеть, что это за строка.

Документы для js-ctype говорят, что если на что-то ссылается CData, то оно будет сохранено. Но мне кажется, что это происходит неправильно.

Если я укажу большой «статический» буфер, такой как

 char *r = "\0....\0";

затем используйте strcpy_s, чтобы скопировать текст в этот буфер и вернуть r, после чего строка пройдет. Если я использую проект DLL с прямым C, но если я пытаюсь сделать это с проектом C ++ / CLR DLL, мне нужно использовать, чтобы получить доступ к моему существующему C # -коду, тогда попытки записи в жестко закодированный буфер вызывают программу врезаться

Так что я вижу три пути продвижения вперед;

  • получить созданные во время выполнения строки для сохранения при переключении обратно с C ++ / CLR на js-ctypes,
  • получить C ++ / CLR, чтобы разрешить мне изменять статический буфер — без проблем с несколькими экземплярами,
  • получить JS для предоставления буфера, который может заполнить C ++ / CLR.

Кто-нибудь знает, как заставить одного из них работать?

0

Решение

Вы не можете вернуть указатель на переменную стека из функции в C — как только функция вернется, эта часть стека будет возвращена, и указатель больше не действителен.

Допустимые альтернативы включают в себя использование статического глобального (осторожно, это не поточно-ориентированного) или наличие функции, выделяющей новую память из кучи, возвращающей указатель на нее и предоставляющей клиентам соответствующую функцию для использования при освобождении памяти, когда они сделали с этим.

3

Другие решения

Если я верну p, я получу «Hello World» обратно. Если я вернусь д, я получаю мусор
или зависание Проверка p и q в отладчике показывает, что они оба содержат
одни и те же данные.

Причиной такого поведения является то, что p указывает на строковую константу, которая хранится в фиксированном месте в сегменте данных DLL — этот адрес остается действительным, пока DLL загружена / сопоставлена.

Тем не мение, q указывает на стек выделенных данных, которые будут исправлены / повторно использованы во время выполнения …

3

По вопросам рекламы [email protected]