2010-05-19 3 views
4

Я мог бы использовать некоторую помощь при назначении глобальной переменной C в DLL с использованием ctypes.Python ctypes in_dll назначение строки

Ниже приведен пример того, что я пытаюсь:

test.c содержит следующую

#include <stdio.h> 

    char name[60]; 

    void test(void) { 
     printf("Name is %s\n", name); 
    } 

на окнах (Cygwin) Я построить DLL (test.dll) следующим образом:

gcc -g -c -Wall test.c 
gcc -Wall -mrtd -mno-cygwin -shared -W1,--add-stdcall-alias -o Test.dll test.o 

При попытке изменить переменную name и затем вызвать функцию теста с помощью интерфейса ctypes я получаю следующее ...

>>> from ctypes import * 
>>> dll = windll.Test 
>>> dll 
<WinDLL 'Test', handle ... at ...> 
>>> f = c_char_p.in_dll(dll, 'name') 
>>> f 
c_char_p(None) 
>>> f.value = 'foo' 
>>> f 
c_char_p('foo') 
>>> dll.test() 
Name is Name is 4∞┘☺ 
13 

Почему тестовая функция печатает мусор в этом случае?

Update:

Я подтвердил ответ Алекса. Вот рабочий пример:

>>> from ctypes import * 
>>> dll = windll.Test 
>>> dll 
<WinDLL 'Test', handle ... at ...> 
>>> f = c_char_p.in_dll(dll, 'name') 
>>> f 
c_char_p(None) 
>>> libc = cdll.msvcrt 
>>> libc 
<CDLL 'msvcrt', handle ... at ...> 
#note that pointer is required in the following strcpy 
>>> libc.strcpy(pointer(f), c_char_p("foo")) 
>>> dll.test() 
Name is foo 
+1

Я проголосовал, но, проведя еще несколько проверок, я думаю, что может произойти что-то еще. Я считаю, что исходный метод OP для присвоения новой строки 'ctype.c_char_p.value' _is_ правильный подход. Меня устраивает. Я также считаю, что подход 'strcpy' может работать здесь, где имя malloc'd имеет 59 + NUL символов, но в другой ситуации может возникнуть ошибка сегментации. –

+0

одна строка кода стоит thausand words: 'f = c_char_p(); buff =" guarda mamma, senza mani! "; F.value = buff; cast (f, POINTER (c_char)) [0] =" G "; печать (бафф) '. Говорить 'f.value =" что-то "ограничивает f тем, что будет жить короткой жизнью. – FxIII

ответ

5

name это на самом деле не персонаж указатель (это массив, который «распадается на» указатель при доступе, но никогда не может быть назначен к). Вам нужно будет вызвать функцию strcpy из библиотеки времени выполнения C, а не назначать f.value.

+0

Мое единственное страх перед этим подходом состояло в том, что 'strcpy (copy, s)' обычно предваряется «copy = malloc (1 + strlen (s))», чтобы убедиться, что у вас есть место для вашей строки. Если вы этого не сделаете, я считаю, что вы можете перезаписать некоторую другую память, если ваше «имя» длиннее, чем 59-символьный буфер + завершающий NULL, который вы выделили. Может закончиться сбоем seg. [См. Документы] (http://www.gnu.org/software/libc/manual/html_node/Copying-and-Concatenation.html). Обычно используется «strdup», который выделяет память «на лету», но я не думаю, что вы могли бы сделать это на Python. –