簡體   English   中英

訪問so文件中的變量並在ctypes中注冊回調函數

[英]access variable in so file and register callback function in ctypes

我正在嘗試從編譯的共享對象訪問在 cpp 頭文件中聲明的變量。 下面是我的情況

/cpp_header.hpp/

#include <stdint.h>
#include <stdio.h>
#include <string.h>

//variables declaration
const uint8_t variable1 = 3;
const uint16_t variable2 = 4056;
const uint16_t variable3 = 3040;

typedef struct {
    void* a;
    uint32_t b
    uint16_t w;
    uint16_t h;
    size_t p;
} structure1 ;

typedef struct {
    uint32_t a;
    uint32_t b
} structure2 ;

//callback function declaration
typedef void (*one_callback) (const structure1 *);
typedef void (*output_callback) (const structure1 *);
typedef void (*inpout_callback) (const structure2 *);

//APIs using the callback function
int start_api(enum_type, output_callback, inpout_callback);

我在 ctypes 中嘗試什么

/ctype_wrapper.py/

import ctypes
from ctypes import *

lib_instance = CDLL('test.so')

#accessing the variable declared in cpp header
variable1 = c_uint8.in_dll(lib_instance, 'variable1')
variable2 = c_uint16.in_dll(lib_instance, 'variable2')
variable3 = c_uint16.in_dll(lib_instance, 'variable2')

//registering callback function
ctype_start_api = lib_instance.start_api
ctype_start_api.argtypes = [enum_type, output_callback, inpout_callback] # register the callback
ctype_start_api.restype = c_int

錯誤輸出

#error for variable access
File "ctype_wrapper.py", line 6, in <module>
    variable1 = c_uint8.in_dll(lib_instance, 'variable1')
ValueError: ./test.so: undefined symbol: variable1

對於回調寄存器,我參考了 ctypes 文檔,但不知道如何為我的場景實現它。

我的變量聲明在 header.hpp 文件中是否正確,或者我需要添加任何內容才能導出已編譯的 so 文件中的變量?

在標題更改中

const uint8_t variable1 = 3;

extern const uint8_t variable1;

並添加這個

extern const uint8_t variable1 = 3;

到 .cpp 文件

默認情況下const變量在 C++ 中具有內部鏈接,因此不會從共享庫中導出。

必須導出變量和函數,以便ctypes找到它們。 extern在 Linux 上可能足以導出變量,但在 Windows 上,變量和函數都需要額外的__declspec(dllexport)聲明。

ctypes還期望導出的變量和函數是 C 鏈接,因此 C++ 變量和函數需要包裝在extern "C"中。

這是一個在 Windows 上測試的工作示例,它還演示了回調:

測試.hpp

#include <stdint.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

typedef struct {
    void* a;
    uint32_t b;
    uint16_t w;
    uint16_t h;
    size_t p;
} structure1;

typedef struct {
    uint32_t a;
    uint32_t b;
} structure2;

typedef void (*output_callback) (const structure1 *);
typedef void (*inpout_callback) (const structure2 *);

extern "C" {

API extern const uint8_t variable1;
API extern const uint16_t variable2;
API extern const uint16_t variable3;

API int start_api(output_callback, inpout_callback);

}

測試.cpp

#include "test.hpp"

extern "C" {

const uint8_t variable1 = 3;
const uint16_t variable2 = 4056;
const uint16_t variable3 = 3040;

int start_api(output_callback ocb, inpout_callback iocb) {
    structure1 s1 { nullptr, 1, 2, 3, 4 };
    structure2 s2 { 5, 6 };
    if(ocb)
        ocb(&s1);
    if(iocb)
        iocb(&s2);
    return 0;
}

}

測試.py

import ctypes as ct

class Structure1(ct.Structure):
    _fields_ = (('a', ct.c_void_p),
                ('b', ct.c_uint32),
                ('w', ct.c_uint16),
                ('h', ct.c_uint16),
                ('p', ct.c_size_t))
    # Good habit: print representation of class so it can print itself.
    def __repr__(self):
        return f'Structure1(a={self.a}, b={self.b}, w={self.w}, h={self.h}, p={self.p})'

class Structure2(ct.Structure):
    _fields_ = (('a', ct.c_uint32),
                ('b', ct.c_uint32))
    def __repr__(self):
        return f'Structure2(a={self.a}, b={self.b})'

OCB = ct.CFUNCTYPE(None, ct.POINTER(Structure1))
IOCB = ct.CFUNCTYPE(None, ct.POINTER(Structure2))

# decorating a function with the callback signature makes it callable from C
@OCB
def output_callback(ps1):
    print(ps1.contents)

@IOCB
def inpout_callback(ps2):
    print(ps2.contents)

lib_instance = ct.CDLL('./test')
start_api = lib_instance.start_api
start_api.argtypes = OCB, IOCB
start_api.restype = ct.c_int

variable1 = ct.c_uint8.in_dll(lib_instance, 'variable1')
variable2 = ct.c_uint16.in_dll(lib_instance, 'variable2')
variable3 = ct.c_uint16.in_dll(lib_instance, 'variable3')

print(variable1.value, variable2.value, variable3.value)
start_api(output_callback, inpout_callback)

輸出:

3 4056 3040
Structure1(a=None, b=1, w=2, h=3, p=4)
Structure2(a=5, b=6)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM