Python функция обратного вызова ctypes с va_list - PullRequest
1 голос
/ 20 марта 2012

У меня проблема с определением функции обратного вызова, используемой dll для получения журнала других функций dll. Вот функция c:

typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list);
void RTMP_LogPrintf(const char *format, ...);

Вот мой код Python:

dll = cdll.LoadLibrary('bin/librtmp.dll')
CMPFUNC = CFUNCTYPE(c_int, c_int, c_char_p, c_void_p)
def logCallBack(level, message, va_list):
    dll.RTMP_LogPrintf(message, va_list)
    return 0

Проблема в том, что журнал грязный и нечитаемый:

    Parsed host    : ☺Parsed app     : ☺connect to stream
ÄßGj♫¨', ... connected, handshaking?ßGj♥: Type Answer   : 27DBEC?ßGjä?┼♣: Server Uptime : 2612204?ßGj♥: FMS Version   : 2612204.2612100.488283845.4882
83530?ßGj♥: Handshaking finished....ÄßGj♫¨', handshaked│°Gj♀☻: fd=2614284, size=2614180Invoking ▒?'ä°Gj♀☻: fd=2618556`÷Gjá%&: server BW = 2618572ä°Gj♀
☻: fd=2618556o÷Gjá%&: client BW = 2618572 2618468ä°Gj♀☻: fd=2618556?÷Gj, received ctrl. type: 2618572, len: 2618468?÷Gj, Stream Begin 2618572ä°Gj♀☻: f
d=26185568÷Gj, received: chunk size change to 2618572ä°Gj♀☻: fd=2618556N÷Gj♣☺, received: invoke 2618572 bytes(object begin)Property: <|±'☺>Property: <
|±'☺>Property: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property: <,´'☺>(object end)Property: <|±'OBJECT>(object begin)Property: <,´'☺
>Property: <,´'☺>Property: <,´'☺>Property: <,´'OBJECT>(object begin)Property: <▄ý'☺>(object end)Property: <,´'☺>Property: <,´'☺>(object end)(object en
d)~÷Gjmt;, server invoking <☺>~÷Gj, received result for method call <☺>│°Gj♀☻: fd=2616844, size=2616740sending ctrl. type: 0x27f264│°Gj♀☻: fd=2616828,
 size=2616724│°Gj♀☻: fd=2616828, size=2616724Invoking ?‗'UsherToken: ú?B☻,☺│°Gj♀☻: fd=2617164, size=2617060Invoking )¶'ä°Gj♀☻: fd=2618556N÷Gj↔, receiv
ed: invoke 2618572 bytes(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'☺>(object end)~÷Gj?⌂;, server invoking <☺>~÷Gj8¶;, r
eceived result for method call <☺>¶÷Gj, seekTime=2617308, stopTime=2617204, sending play: â─↑?♥â╚*?e¶╔├U?ýâý►SVW?¨?w►?E*ëE??F♦┴Ó☻?┌??↨│°Gj♀☻: fd=26171
64, size=2617060Invoking )¶'sending ctrl. type: 0x27f264│°Gj♀☻: fd=2616828, size=2616724ä°Gj♀☻: fd=2618556N÷Gj%, received: invoke 2618572 bytes(object
 begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'☺>(object end)~÷Gj?⌂;, server invoking <☺>~÷Gj, received result id 2617308 without
matching requestä°Gj♀☻: fd=2618556?÷Gj, received ctrl. type: 2618572, len: 2618468?÷Gj☺, Stream Begin 2618572ä°Gj♀☻: fd=2618556N÷Gjö, received: invoke
 2618572 bytes(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property:
 <,´'☺>Property: <,´'☺>(object end)(object end)~÷Gj?t;, server invoking <☺>~÷Gj┴t;, onStatus: ☺ä°Gj♀☻: fd=2618556N÷Gj?, received: invoke 2618572 bytes
(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property: <,´'☺>Propert, ...etc

Я также пытался напечатать сообщение прямо так:

def logCallBack(level, message, va_list):
    print message
    return 0

но на этот раз журнал неполон:

%s, ... connected, handshaking
%s: Type Answer   : %02X
%s: Server Uptime : %d
%s: FMS Version   : %d.%d.%d.%d
%s: Handshaking finished....
%s, handshaked
%s: fd=%d, size=%d
Invoking %s
%s: fd=%d
%s: server BW = %d
%s: fd=%d
%s: client BW = %d %d
%s: fd=%d
%s, received ctrl. type: %d, len: %d
... etc

Кто-нибудь знает, как решить эту проблему?

Заранее спасибо.

С уважением, Гонтран

РЕДАКТИРОВАТЬ:

в соответствии с этим потоком (http://www.digipedia.pl/usenet/thread/15901/197/), ctypes не обеспечивает способ работы с функциями varargs. Я понял это. Но почему использование функции RTMP_LogPrintf () не работает правильно? Такое впечатление, что я передаю правильные аргументы.

Для информации RTMP_LogPrintf () определяется следующим образом:

void RTMP_LogPrintf(const char *format, ...)
{
    char str[MAX_PRINT_LEN]="";
    int len;
    va_list args;
    va_start(args, format);
    len = vsnprintf(str, MAX_PRINT_LEN-1, format, args);
    va_end(args);

    if ( RTMP_debuglevel==RTMP_LOGCRIT )
        return;

    if ( !fmsg ) fmsg = stderr;

    if (neednl) {
        putc('\n', fmsg);
        neednl = 0;
    }

    if (len > MAX_PRINT_LEN-1)
          len = MAX_PRINT_LEN-1;
    fprintf(fmsg, "%s", str);
    if (str[len-1] == '\n')
        fflush(fmsg);
}

Ответы [ 2 ]

0 голосов
/ 04 мая 2013

попробуйте

CMPFUNC = CFUNCTYPE(c_int, c_int, POINTER(c_char), c_void_p)
0 голосов
/ 28 июля 2012

Предположим, что тип va_list действительно может быть представлен как c_void_p (что является ошибочным предположением). Несмотря на это, следующий вызов неверен:

dll.RTMP_LogPrintf(message, va_list)

Вы передаете здесь ровно два аргумента, а второй - void *. Это та же ошибка, что и в C, если бы вы написали

RTMP_LogPrintf(message, va_list);

, который не работает, как ожидалось. Вот почему есть две разные функции printf() и vprintf(). В C нет переносимого способа создания вызова с переменным числом аргументов (только получатель может принимать переменное количество аргументов). В Python + ctypes вы, конечно, можете это сделать, но вам нужно, чтобы аргументы были доступны в виде списка объектов Python, а не просто как один va_list объект.

...