简体   繁体   English

将 char* 数组从 c dll 传递到 python

[英]Pass char* array from c dll to python

I have simple dll with function which taks callback as parameter and calls it sometimes passing unsigned char* array.我有简单的 dll 和 function ,它将回调作为参数并调用它有时传递 unsigned char* 数组。 I want to use it in python.我想在 python 中使用它。

Here is dll source:这是 dll 来源:

typedef void (*buffer_ready_callback_t)(unsigned char* data, int len);

extern "C" void __declspec(dllexport) example(buffer_ready_callback_t cb) {
     unsigned char* data = (unsigned char*)malloc(100);
     memset(data,0xAA,100);
     
     cb(data,100);

     free(data);
}

and in python I use it like this:在 python 我这样使用它:

library = cdll.LoadLibrary("example.dll")
buffer_ready_callback_t = CFUNCTYPE(None, c_char_p, c_int, c_ulong)

def api_callback_buffer(self, data, ln, ts):    
        #problem here
        pass

function = self.library.example
function.restype = None
function.argtypes = [buffer_ready_callback_t]
api_buffer_cb = buffer_ready_callback_t(api_callback_buffer)        
function(api_buffer_cb);

So question is how to use data received in callback function?那么问题是如何使用回调 function 中收到的数据? Is it possible to convert to bytearray or list or or numpy array or something else that can be used in python?是否可以转换为字节数组或列表或 numpy 数组或其他可用于 python 的数组?

Thanks谢谢

Listing [Python.Docs]: ctypes - A foreign function library for Python .清单[Python.Docs]:ctypes - 用于 Python 的外部 function 库

The question is a bit unclear.这个问题有点不清楚。 Given existing code, you should already have the data as bytes in your callback function.给定现有代码,您应该已经在回调 function 中将数据作为字节保存。

Here's an example.这是一个例子。

dll00.c : dll00.c

#include <stdio.h>
#include <stdlib.h>

#if defined(_WIN32)
#  define DLL00_EXPORT_API __declspec(dllexport)
#else
#  define DLL00_EXPORT_API
#endif


typedef void (*Callback)(unsigned char *pData, int len);

#if defined(__cplusplus)
extern "C" {
#endif

DLL00_EXPORT_API void dll00Func00(Callback cb, unsigned int len, unsigned char fillValue);

#if defined(__cplusplus)
}
#endif


void dll00Func00(Callback cb, unsigned int len, unsigned char fillValue) {
    unsigned char *pData = malloc(len);
    memset(pData, fillValue, len);
    cb(pData, len);
    free(pData);
    pData = NULL;
}

code00.py :代码00.py

#!/usr/bin/env python

import sys
import ctypes as ct


CharArray = ct.POINTER(ct.c_char)  # #1: Use ct.POINTER(ct.c_char) instead of ct.c_char_p as 2nd arg type
#CharArray = ct.c_char_p
Callback = ct.CFUNCTYPE(None, CharArray, ct.c_int)

DLL_NAME = "./dll00.dll"

DATA_LEN = 0x100


def func(data, length):
    print("Length: {0:d}".format(length))
    print(type(data))
    print("Elements:")
    for idx in [0, DATA_LEN - 1]:
        print("  {0:3d} - {1:}".format(idx, data[idx]))
    b = b"".join((data[i] for i in range(length)))
    print(type(b), len(b), b)


def main(*argv):
    dll00 = ct.CDLL(DLL_NAME)
    dll00Func00 = dll00.dll00Func00
    dll00Func00.argtypes = (Callback, ct.c_uint, ct.c_ubyte)
    dll00Func00.restype = None

    dll00Func00(Callback(func), DATA_LEN, 0xAA)  # #2: Pass 0x00 as 3rd arg and uncomment line #8, and you'll see what I meant in the 1st note


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

Output : Output

 [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q063190506]> sopr.bat *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2017\VC\Auxiliary\Build\vcvarsall.bat" x64 ********************************************************************** ** Visual Studio 2017 Developer Command Prompt v15.9.25 ** Copyright (c) 2017 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x64' [prompt]> dir /b code00.py dll00.c [prompt]> cl /nologo /MD /DDLL dll00.c /link /NOLOGO /DLL /OUT:dll00.dll dll00.c Creating library dll00.lib and object dll00.exp [prompt]> dir /b code00.py dll00.c dll00.dll dll00.exp dll00.lib dll00.obj [prompt]> [prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Length: 256 <class 'ctypes.LP_c_char'> Elements: 0 - b'\xaa' 255 - b'\xaa' <class 'bytes'> 256 b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' Done.

Notes :备注

  • c_char_p is to be used with NUL terminated strings, using it here would be incorrect (even if apparently everything seems OK ) c_char_p将与NUL终止的字符串一起使用,在这里使用它是不正确的(即使显然一切看起来都不错)
  • The example is a bit more complex (to easily exemplify the previous bullet)这个例子有点复杂(为了方便地举例说明上一个项目符号)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM