Как перевести приведение адреса памяти в C в вызов Python ctypes? - PullRequest
0 голосов
/ 10 апреля 2011

Извините, если заголовок не точный, я не уверен на 100%, что он правильно описывает ситуацию:

Я пытаюсь взаимодействовать с C-библиотекой FreeTDS с помощью модуля Python ctypes.У меня какой-то код работает на удивление хорошо, но наткнулся на одну загадку.Я не уверен, как перевести последний параметр вызова dbbind () ниже в ctypes.

Ниже приведен пример C:

  /* these variable types are defined in the FreeTDS library */
  DBINT customer_id;
  DBCHAR company_name[255];
  DBFLT8 avg_income;

  /* <snip> */


  /* Now bind the returned columns to the variables */
  /* BYTE is defined in the FreeTDS library */
  dbbind(dbconn, 1, INTBIND, 0, (BYTE *)&customer_id);
  dbbind(dbconn, 2, NTBSTRINGBIND, 0, (BYTE *)&company_name);
  dbbind(dbconn, 3, FLT8BIND, 0, (BYTE*)&avg_income);

Итак, A) как определить мои переменные в Python как типы переменных из библиотеки и B) как перевести "(BYTE *) & company_name "и т. Д. На вызовы ctypes?

Спасибо!

Решение: благодаря Зульджину я смог решить следующее:

import ctypes as ct

#<snip>

cid = ct.c_int()
cname = ct.create_string_buffer(256)
cavgincome = ct.c_float()
dtlib.dbbind(cdbconn, 1, INTBIND, 0, ct.byref(cid))
dtlib.dbbind(cdbconn, 2, NTBSTRINGBIND, 0, cname)
dtlib.dbbind(cdbconn, 3, REALBIND, 0, ct.byref(cavgincome))

while dtlib.dbnextrow(cdbconn) != NO_MORE_ROWS:
    print '%s | %s | %s' % (cid, cname.value, cavgincome)

1 Ответ

3 голосов
/ 10 апреля 2011

Я думаю, вы должны просто проверить, что стоит за этими типами DBINT, DBCHAR, DBFLT8.Вероятно, это int, char и double.И для этих основных типов вы можете найти ctypes - вероятно, c_int, c_char, c_double.Теперь вы можете создавать экземпляры Python, которые будут содержать значения, возвращаемые функцией.Чтобы передать эти значения в качестве параметра указателя, вам нужно использовать функцию byref().Примерно так:

customer_id = c_int()
dbbind(dbconn, 1, INTBIND, 0, byref(customer_id))

РЕДАКТИРОВАТЬ: Для имени вы должны создать пустой символьный буфер.Для этого ctypes предоставляют 2 функции create_string_buffer и create_unicode_buffer.Выходной объект из этих функций может быть напрямую передан вашей функции.Вот пример (в Python 3) обычного и юникодного вызова функции scanf в Windows.

from ctypes import *
libc = cdll.msvcrt

buf = create_string_buffer(256) 
buf_u = create_unicode_buffer(256)

libc.scanf(b"%s",  buf)
libc.wscanf("%s",  buf_u)

print(buf.value)
print(buf_u.value)
...