- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个关于 Python 的 ctypes 和调用 C 函数的问题困扰了我几天。我正在使用 Python 3.5 和 ctypes 来包装 C .dll。
我有一个接受 void **
作为输出参数的 C 函数。这应该包含一个指向调用后图像的一些 8 位 RGB 数据的指针。
foo(void ** bar)
我声明我的 Python 参数和函数调用如下:
>>bar = c_void_p()
>>foo(byref(bar))
并尝试接收数据:
>>data = c_byte(bar.value)
>>data.value
20
这实际上是第一个像素“R”字节的合理值但是我没有设法达到除此之外的任何字节。根据我的理解,我现在得到 c_void_p 指向的第一个字节的值(?)
我也试过:
>>data = (c_byte*3)(bar.value)
3 仅用于测试目的(尝试并增加到几千):
>>data
<__main__.c_byte_Array_3 at 0x7faca45de950> #so far so good again?
>>data[0]
20
>>data[1]
0
...
>>data[n]
0
对我来说,我似乎无法再访问更多字节?
当我尝试将 bar
定义为 int 指针(很多人都推荐这样做)时,我得到以下信息:
>>bar = POINTER(c_int)()
>>foo(byref(bar))
>>bar
<__main__.LP_c_int at 0x7fcf71d9d8c8> #so far so good?
>>bar.contents
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
我还处理了我在网上找到的所有内容,包括: this , this ,还有一些我现在找不到。
非常感谢任何帮助!
编辑:python文件的全部代码:
from ctypes import *
from ctypes_wrapper_dijsdk import *
init()
guids = find_cameras()
handle = c_void_p()
open_camera(guids, handle, 0)
start_acquisition(handle, 1)
imageHandle = c_void_p()
VOIDPP = POINTER(c_void_p)
imageData = VOIDPP(c_void_p())
get_image(handle, imageHandle, imageData)
byte_buf = cast(imageData.contents, POINTER(c_ubyte * (1920)))
for x in range(0, (1920)-1 ):
print("value: {:3d}".format(byte_buf.contents[x]))
dimension = (c_int*2)()
get_int_parameter(imageHandle, 0x20000103, dimension, 2)
value = c_void_p()
get_int_parameter(imageHandle, 0x20000200, value)
#from now on would be able to get the ImageData Size
print("ImageFormat = ", value.value, "see SDK.h")
release_image(imageHandle)
close_camera(handle)
exit()
从 python 调用到 C:
def get_image(handle, imageHandle, imageData, timeout = 0):
return d.SDK_GetImage(handle, byref(imageHandle), imageData, timeout)
附加信息:
代码中其实还有更多的void**
输出参数,比如imageHandle
。但它们不处理任何数组,而且似乎工作得很好。它们被声明为 c_void_p
并被称为 byref( )
。
RGB 数据存储为每行像素的字节流。所以它的维度[0] x 维度[1] x 位深度长。
我无法提供任何 C 代码,因为它是共享库的一部分。
最佳答案
这是一种做事方式。此外,ctypes 的官方文档:[Python 3.5]: ctypes - A foreign function library for Python .
dll.c:
#include <stdio.h>
#include <stdlib.h>
#if defined(_WIN32)
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
#define C_TAG "From C"
#define PRINT_MSG_0() printf("%s - [%s] (%d) - [%s]\n", C_TAG, __FILE__, __LINE__, __FUNCTION__)
#define PRINT_ERR_1S(ARG0) printf("%s: %s\n", C_TAG, ARG0)
DLL_EXPORT int test(void **pptr, size_t count) {
PRINT_MSG_0();
if (!pptr) {
PRINT_ERR_1S("NULL pointer received");
return -1;
}
if (*pptr) {
PRINT_ERR_1S("Non NULL inner pointer received");
return -2;
}
unsigned char *buf = (unsigned char*)malloc(count);
for (size_t i = 0; i < count; i++) {
buf[i] = (i + 1) % 0x100;
}
*pptr = buf;
return 0;
}
DLL_EXPORT void dealloc(void **pptr) {
PRINT_MSG_0();
if ((pptr) && (*pptr)) {
free(*pptr);
*pptr = NULL;
}
}
代码.py:
import sys
import math
from ctypes import c_ubyte, c_int, c_size_t, c_void_p, \
POINTER, CDLL, \
cast
VoidPtrPtr = POINTER(c_void_p)
dll_dll = CDLL("./dll.dll")
test_func = dll_dll.test
test_func.argtypes = [VoidPtrPtr, c_size_t]
test_func.restype = c_int
dealloc_func = dll_dll.dealloc
dealloc_func.argtypes = [c_void_p]
DISPLAY_VALUES_COUNT = 5
FORMAT_STRING_PAT = " idx: {{:{:d}d}} - value: {{:3d}}"
def _get_print_indexes(array_size, values_count):
if array_size <= 0 or values_count <= 1 or values_count > array_size:
raise ValueError("Invalid args")
yield 0
if array_size > 1:
if values_count > 2:
interval_size = array_size / (values_count - 1)
for idx in range(1, values_count - 1):
yield int(round(idx * interval_size))
yield array_size - 1
def _print_array_values(array, array_size, values_count=DISPLAY_VALUES_COUNT):
index_width = math.ceil(math.log10(array_size))
format_string = FORMAT_STRING_PAT.format(index_width)
for idx in _get_print_indexes(array_size, values_count):
print(format_string.format(idx, array.contents.contents[idx]))
def main():
sizes = [
10,
100,
500,
1920 * 1080 * 3,
]
for size in sizes:
UByteArr = c_ubyte * size
UByteArrPtr = POINTER(UByteArr)
UByteArrPtrPtr = POINTER(UByteArrPtr)
print("\nSize: {:d}".format(size))
data = UByteArrPtrPtr(UByteArrPtr())
print("data: {:}, data.contents: {:}".format(data, data.contents))
#print(addressof(data), addressof(data.contents))
ptr = cast(data, VoidPtrPtr)
res = test_func(ptr, size)
if res < 0:
print("{:s} returned {:d}. Moving on...\n".format(test_func.__name__, res))
continue
print("data: {:}, data.contents: {:}".format(data, data.contents))
_print_array_values(data, size)
dealloc_func(data)
print("data: {:}, data.contents: {:}".format(data, data.contents))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
注意事项:
void **
) 没有多大意义)。这给代码增加了一些复杂性(除其他事项外:dealloc
- 以避免内存泄漏)。使用后一个选项会“生成”更少的代码,并且不需要 void**
(我仍然想知道为什么仍然需要它)void*
是一个通用类型,信息不多。这就是为什么在 C 中,为了填充各个字节,我必须将其转换 为 unsigned char *
。同样的事情也适用于 Python。我在 Python 中表达 void **
的方式是通过 POINTER(c_void_p)
_get_print_indexes
,仅用于选择 5(DISPLAY_VALUES_COUNT
)等距 (从索引的角度)数组中的元素_print_array_values
- 打印值输出:
(py35x64_test) e:\Work\Dev\StackOverflow\q051981858>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64
(py35x64_test) e:\Work\Dev\StackOverflow\q051981858>dir /b
code.py
dll.c
(py35x64_test) e:\Work\Dev\StackOverflow\q051981858>cl /nologo dll.c /DDLL /link /DLL /OUT:dll.dll
dll.c
Creating library dll.lib and object dll.exp
(py35x64_test) e:\Work\Dev\StackOverflow\q051981858>dir /b
code.py
dll.c
dll.dll
dll.exp
dll.lib
dll.obj
(py35x64_test) e:\Work\Dev\StackOverflow\q051981858>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Size: 10
data: <__main__.LP_LP_c_ubyte_Array_10 object at 0x000001F8189FBBC8>, data.contents: <__main__.LP_c_ubyte_Array_10 object at 0x000001F8189FBC48>
From C - [dll.c] (16) - [test]
data: <__main__.LP_LP_c_ubyte_Array_10 object at 0x000001F8189FBBC8>, data.contents: <__main__.LP_c_ubyte_Array_10 object at 0x000001F8189FBCC8>
idx: 0 - value: 1
idx: 2 - value: 3
idx: 5 - value: 6
idx: 8 - value: 9
idx: 9 - value: 10
From C - [dll.c] (35) - [dealloc]
data: <__main__.LP_LP_c_ubyte_Array_10 object at 0x000001F8189FBBC8>, data.contents: <__main__.LP_c_ubyte_Array_10 object at 0x000001F8189FBD48>
Size: 100
data: <__main__.LP_LP_c_ubyte_Array_100 object at 0x000001F8189FBCC8>, data.contents: <__main__.LP_c_ubyte_Array_100 object at 0x000001F8189FBDC8>
From C - [dll.c] (16) - [test]
data: <__main__.LP_LP_c_ubyte_Array_100 object at 0x000001F8189FBCC8>, data.contents: <__main__.LP_c_ubyte_Array_100 object at 0x000001F8189FBC48>
idx: 0 - value: 1
idx: 25 - value: 26
idx: 50 - value: 51
idx: 75 - value: 76
idx: 99 - value: 100
From C - [dll.c] (35) - [dealloc]
data: <__main__.LP_LP_c_ubyte_Array_100 object at 0x000001F8189FBCC8>, data.contents: <__main__.LP_c_ubyte_Array_100 object at 0x000001F8189FBE48>
Size: 500
data: <__main__.LP_LP_c_ubyte_Array_500 object at 0x000001F8189FBC48>, data.contents: <__main__.LP_c_ubyte_Array_500 object at 0x000001F8189FBEC8>
From C - [dll.c] (16) - [test]
data: <__main__.LP_LP_c_ubyte_Array_500 object at 0x000001F8189FBC48>, data.contents: <__main__.LP_c_ubyte_Array_500 object at 0x000001F8189FBDC8>
idx: 0 - value: 1
idx: 125 - value: 126
idx: 250 - value: 251
idx: 375 - value: 120
idx: 499 - value: 244
From C - [dll.c] (35) - [dealloc]
data: <__main__.LP_LP_c_ubyte_Array_500 object at 0x000001F8189FBC48>, data.contents: <__main__.LP_c_ubyte_Array_500 object at 0x000001F8189FBF48>
Size: 6220800
data: <__main__.LP_LP_c_ubyte_Array_6220800 object at 0x000001F8189FBDC8>, data.contents: <__main__.LP_c_ubyte_Array_6220800 object at 0x000001F818A62048>
From C - [dll.c] (16) - [test]
data: <__main__.LP_LP_c_ubyte_Array_6220800 object at 0x000001F8189FBDC8>, data.contents: <__main__.LP_c_ubyte_Array_6220800 object at 0x000001F8189FBEC8>
idx: 0 - value: 1
idx: 1555200 - value: 1
idx: 3110400 - value: 1
idx: 4665600 - value: 1
idx: 6220799 - value: 0
From C - [dll.c] (35) - [dealloc]
data: <__main__.LP_LP_c_ubyte_Array_6220800 object at 0x000001F8189FBDC8>, data.contents: <__main__.LP_c_ubyte_Array_6220800 object at 0x000001F8189FBEC8>
@EDIT0:
_print_array_values
)POINTER
包装(类似于按值传递 类型)以便等价 到指针(并从/转换到它)关于python - 取消引用 c_void_p 的整个数据,而不仅仅是第一个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51981858/
美好的一天!我试图添加两个字节变量并注意到奇怪的结果。 byte valueA = 255; byte valueB = 1; byte valueC = (byte)(valueA + valueB
嗨,我是 swift 的新手,我正在尝试解码以 [Byte] 形式发回给我的字节数组?当我尝试使用 if let string = String(bytes: d, encoding: .utf8)
我正在使用 ipv4 和 ipv6 存储在 postgres 数据库中。 因为 ipv4 需要 32 位(4 字节)而 ipv6 需要 128(16 字节)位。那么为什么在 postgres 中 CI
我很好奇为什么 Go 不提供 []byte(*string) 方法。从性能的角度来看,[]byte(string) 不会复制输入参数并增加更多成本(尽管这看起来很奇怪,因为字符串是不可变的,为什么要复
我正在尝试为UDP实现Stop-and-Wait ARQ。根据停止等待约定,我在 0 和 1 之间切换 ACK。 正确的 ACK 定义为正确的序列号(0 或 1)AND消息长度。 以下片段是我的代码的
我在下面写了一些代码,目前我正在测试,所以代码中没有数据库查询。 下面的代码显示 if(filesize($filename) != 0) 总是转到 else,即使文件不是 0 字节而是 16 字节那
我使用 Apache poi 3.8 来读取 xls 文件,但出现异常: java.io.IOException: Unable to read entire header; 0 by
字典大小为 72 字节(根据 getsizeof(dict) 在字典上调用 .clear() 之后发生了什么,当新实例化的字典返回 240 字节时? 我知道一个简单的 dict 的起始大小为“8”,并
我目前正在努力创建一个函数,它接受两个 4 字节无符号整数,并返回一个 8 字节无符号长整数。我试图将我的工作基于 this research 描述的方法,但我的所有尝试都没有成功。我正在处理的具体输
看看这个简单的程序: #include using namespace std; int main() { unsigned int i=0x3f800000; float* p=(float*)(
我创建了自己的函数,将一个字符串转换为其等效的 BCD 格式的 bytes[]。然后我将此字节发送到 DataOutputStram (使用需要 byte[] 数组的写入方法)。问题出在数字字符串“8
此分配器将在具有静态内存的嵌入式系统中使用(即,没有可用的系统堆,因此“堆”将只是“char heap[4096]”) 周围似乎有很多“小型内存分配器”,但我正在寻找能够处理非常小的分配的一个。我说的
我将数据库脚本从 64 位系统传输到 32 位系统。当我执行脚本时,出现以下错误, Warning! The maximum key length is 900 bytes. The index 'U
想知道 128 字节 ext2 和 256 字节 ext3 文件系统之间的 inode 数据结构差异。 我一直在为 ext2、128 字节 inode 使用此引用:http://www.nongnu.
我试图理解使用 MD5 哈希作为 Cassandra key 在“内存/存储消耗”方面的含义: 我的内容(在 Java 中)的 MD5 哈希 = byte[] 长 16 个字节。 (16 字节来自维基
检查其他人是否也遇到类似问题。 shell脚本中的代码: ## Convert file into Unix format first. ## THIS is IMPORTANT. ###
我们有一个测量数据处理应用程序,目前所有数据都保存为 C++ float,这意味着在我们的 x86/Windows 平台上为 32 位/4 字节。 (32 位 Windows 应用程序)。 由于精度成
我读到在 Java 中 long 类型可以提升为 float 和 double ( http://www.javatpoint.com/method-overloading-in-java )。我想问
我有一个包含 n 个十进制元素的列表,其中每个元素都是两个字节长。 可以说: x = [9000 , 5000 , 2000 , 400] 这个想法是将每个元素拆分为 MSB 和 LSB 并将其存储在
我使用以下代码进行 AES-128 加密来编码一个 16 字节的 block ,但编码值的长度给出了 2 个 32 字节的 block 。我错过了什么吗? plainEnc = AES.enc
我是一名优秀的程序员,十分优秀!