P0W*_*P0W 0 c python dll ctypes
我.DLL使用其中的一些实用程序函数创建了"命名"共享内存
我需要struct使用具有以下原型的函数通过python 写入/读取C :
int write_shmem(const char* shmem_name, char* shmem) int read_shmem ( const char* shmem_name , char* shmem);在.DLL文件中
shmem_name 是共享内存名称shmem 是要写的数据C struct类似于
typedef struct {
unsigned char c;
unsigned long l;
float f;
double d;
} DataBlock ;
Run Code Online (Sandbox Code Playgroud)
我在python代码中使用以下
from ctypes import *
dll = cdll.LoadLibrary('shared_mem.dll')
write_shmem = dll.write_shmem
write_shmem.restype = ctypes.c_int
read_shmem = dll.read_shmem
read_shmem.restype = ctypes.c_int
class DataBlock(Structure):
_fields_ = [('c', c_ubyte), ('l', c_ulong),
('f',c_float), ('d', c_double) ]
data = DataBlock('A',123, 12.32, 1.89721)
write_shmem(c_char_p(b'P0W') , ??? ) # cast(data, POINTER(c_char) ?
#...
read_shmem(c_char_p(b'P0W'), ??? ) # cast(data, POINTER(c_char) ?
Run Code Online (Sandbox Code Playgroud)
如何进行类型转换char*?
使用cast会正确地将数据放入共享内存吗?我需要从C应用程序中读取相同的共享内存
编辑
使用:
int create_shmem(const char*, long long );从.DLL我创建一个"命名的"共享内存
Python代码:
create_shmem( c_char_p(b'P0W'),
ctypes.c_longlong(sizeof(DataBlock)) )
Run Code Online (Sandbox Code Playgroud)
write_shmem并将 read_shmem使用创建的内存大小简单地写/读数据.这是在.DLL函数本身完成的.(Boost此处使用进程间共享内存对象)
使用Python版本:3.3.0
我没有你的版本read_shmem和write_shmem功能.所以我创建了以下虚拟版本:
#include <stdio.h>
typedef struct {
unsigned char c;
unsigned long l;
float f;
double d;
} DataBlock ;
int write_shmem(const char* shmem_name, char* data)
{
DataBlock* block = (DataBlock*)data ;
printf("%c %ld %f %lf\n", block->c, block->l, block->f, block->d) ;
return sizeof(DataBlock) ;
}
int read_shmem(const char* shmem_name, char* data)
{
DataBlock* block = (DataBlock*)data ;
block->c = 'z' ;
block->l = 3 ;
block->f = block->d = 3.14 ;
return sizeof(DataBlock) ;
}
Run Code Online (Sandbox Code Playgroud)
在Python代码中,我可以这样调用它们:
#! /usr/bin/env python3
from ctypes import *
dll = cdll.LoadLibrary('./libshmem.so')
write_shmem = dll.write_shmem
write_shmem.restype = c_int
read_shmem = dll.read_shmem
read_shmem.restype = c_int
class DataBlock(Structure):
_fields_ = [('c', c_ubyte), ('l', c_ulong),
('f',c_float), ('d', c_double) ]
#
# Using byref()
#
data = DataBlock(ord('A'), 123, 12.32, 1.89721)
write_shmem(b"P0W", byref(data))
read_shmem(b"P0W", byref(data))
print("{0} {1} {2} {3}".format(chr(data.c), data.l, data.f, data.d))
#
# Using pointer()
#
data = DataBlock(ord('A'), 123, 12.32, 1.89721)
write_shmem(b"P0W", pointer(data))
read_shmem(b"P0W", pointer(data))
print("{0} {1} {2} {3}".format(chr(data.c), data.l, data.f, data.d))
#
# Using cast()
#
data = DataBlock(ord('A'), 123, 12.32, 1.89721)
write_shmem(b"P0W", cast(pointer(data), c_char_p))
read_shmem(b"P0W", cast(pointer(data), c_char_p))
print("{0} {1} {2} {3}".format(chr(data.c), data.l, data.f, data.d))
Run Code Online (Sandbox Code Playgroud)
在每种情况下的输出(byref,pointer,或cast使用)是:
A 123 12.320000 1.897210
z 3 3.140000104904175 3.14
Run Code Online (Sandbox Code Playgroud)
我正在使用Linux,因此我使用以下代码从C代码创建共享对象库Makefile:
libshmem.so: dummy_shmem.o
gcc -shared -o libshmem.so dummy_shmem.o
dummy_shmem.o: dummy_shmem.c
gcc -fpic -c dummy_shmem.c
Run Code Online (Sandbox Code Playgroud)
但是Windows上的行为应该大致相同.
请注意,使用write_shmem和read_shmem隐式了解传递给它们的数据缓冲区的大小是危险的.如果您不小心将另一种类型的对象传递给它们,您将得到奇怪的结果.更安全的选择可能是围绕这些函数创建填充程序以显式管理DataBlock实例.下面是一个例子,我有虚拟实现方式create_shmem,write_shmem以及read_shmem:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
typedef struct {
unsigned char c;
unsigned long l;
float f;
double d;
} DataBlock ;
static char* dummy_shmem = 0 ;
static size_t shmem_size = 0 ;
int create_shmem(const char* shmem_name, const size_t data_size)
{
free(dummy_shmem) ;
dummy_shmem = 0 ;
shmem_size = 0 ;
dummy_shmem = malloc(data_size) ;
shmem_size = dummy_shmem ? data_size : 0 ;
return shmem_size ;
}
int write_shmem(const char* shmem_name, const char* data, const size_t data_size)
{
if (data_size <= shmem_size) {
memcpy(dummy_shmem, data, data_size) ;
return data_size ;
}
return 0 ;
}
int read_shmem(const char* shmem_name, char* data, const size_t data_size)
{
if (data_size <= shmem_size) {
memcpy(data, dummy_shmem, data_size) ;
return data_size ;
}
return 0 ;
}
int create_block(const char* shmem_name)
{
printf("create_block: %s\n", shmem_name) ;
return create_shmem(shmem_name, sizeof(DataBlock)) ;
}
int write_block(const char* shmem_name, const DataBlock* data)
{
printf("write_block: [%s] %c %ld %f %lf\n", shmem_name, data->c, data->l, data->f, data->d) ;
return write_shmem(shmem_name, (char*)data, sizeof(DataBlock)) ;
}
DataBlock read_block(const char* shmem_name)
{
DataBlock result ;
read_shmem(shmem_name, (char*)&result, sizeof(DataBlock)) ;
printf("read_block: [%s] %c %ld %f %lf\n", shmem_name, result.c, result.l, result.f, result.d) ;
return result ;
}
Run Code Online (Sandbox Code Playgroud)
然后Python代码变得更简单,更清晰,更安全:
#! /usr/bin/env python3
from ctypes import *
dll = cdll.LoadLibrary('./libshmem.so')
class DataBlock(Structure):
_fields_ = [('c', c_ubyte), ('l', c_ulong),
('f',c_float), ('d', c_double) ]
create_block = dll.create_block
create_block.argtypes = [c_char_p]
create_block.restype = c_int
write_block = dll.write_block
write_block.argtypes = [c_char_p, POINTER(DataBlock)]
write_block.restype = c_int
read_block = dll.read_block
read_block.argtypes = [c_char_p]
read_block.restype = DataBlock
#
# Create memory block
#
create_block(b"P0W")
#
# Write data block to shmem
#
in_data = DataBlock(ord('A'), 123, 12.32, 1.89721)
write_block(b"P0W", in_data)
#
# Read data block from shmem.
#
out_data = read_block(b"P0W")
print("{0} {1} {2} {3}".format(chr(in_data.c), in_data.l, in_data.f, in_data.d))
print("{0} {1} {2} {3}".format(chr(out_data.c), out_data.l, out_data.f, out_data.d))
Run Code Online (Sandbox Code Playgroud)
更新:
DataBlock参考write_block(见下文eryksun的评论).