将C结构传递给C DLL中的函数

2024-09-29 00:21:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个.DLL,它使用其中的一些实用函数创建“命名”共享内存

我需要使用具有以下原型的函数通过python编写/读取以下Cstruct

  • int write_shmem(const char* shmem_name, char* shmem)
  • int read_shmem ( const char* shmem_name , char* shmem);

.DLL文件中

  • shmem_name是共享内存名
  • shmem是要写入的数据

Cstruct

typedef struct {
   unsigned char c;
   unsigned long l;
   float f;
   double d;
 } DataBlock ;

我在python代码中使用了以下内容

^{pr2}$

如何将类型转换为char*?在

使用强制转换能正确地将数据放入共享内存吗?我需要从C应用程序读取相同的共享内存

编辑

使用:

int create_shmem(const char*, long long );来自.DLL我正在创建一个“命名的”共享内存

Python代码:

create_shmem( c_char_p(b'P0W'),
               ctypes.c_longlong(sizeof(DataBlock)) )

write_shmem和{}将使用创建的内存大小来简单地写入/读取数据。这是在.DLL函数本身中完成的。(Boost此处使用进程间共享内存对象)

使用Python版本:3.3.0


Tags: 数据函数name命名longwriteintdll
1条回答
网友
1楼 · 发布于 2024-09-29 00:21:55

我没有您的read_shmemwrite_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) ;
}

在Python代码中,我可以这样调用它们:

^{pr2}$

在每种情况下(^{}^{},或^{}用法)的输出是:

^{3}$

我正在使用Linux,因此我使用以下Makefile从C代码创建一个共享对象库:

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

但是在Windows上的行为应该是一样的。在

主动建议

请注意,使用write_shmem和{}并隐含传递给它们的数据缓冲区的大小是危险的。如果不小心将另一种类型的对象传递给它们,则会得到奇怪的结果。一个更安全的选择可能是围绕这些函数创建垫片来显式地管理DataBlock实例。下面是一个示例,其中我有create_shmemwrite_shmemread_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 ;
}

这样,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))

更新:

  • 通过引用DataBlock传递write_block(参见下面的eryksun注释)。在

相关问题 更多 >