You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中访问KMP生成DLL的C嵌套结构体指针

如何用Python ctypes访问Kotlin Native生成的DLL结构体成员?

问题背景

Kotlin Multiplatform/Native生成的Windows DLL对应C头文件片段:

typedef struct {
  struct {
    struct {
      // ...
    } root;
  } kotlin;
} libnative_ExportedSymbols;
extern libnative_ExportedSymbols* libnative_symbols(void);

C语言中访问root结构体的方式:

libnative_ExportedSymbols* lib = libnative_symbols();
lib->kotlin.root. // ...

尝试用Python ctypes访问时多次触发AttributeError,代码如下:

import ctypes

libPath = "path/to/libnative.dll"
dll = ctypes.CDLL(libPath)
pythonInt = dll.libnative_symbols()

print(type(pythonInt)) # <class 'int'>
print(pythonInt) # A number, e.g. 1190351680

CPointer = ctypes.POINTER(ctypes.c_long)
cLong = ctypes.c_long(pythonInt)
cAddress = ctypes.addressof(cLong)
cPointer = ctypes.cast(cAddress, CPointer)

print(type(pythonInt) == type(cPointer.contents.value)) # true
print(pythonInt == cPointer.contents.value) # true
try:
    print(cPointer.kotlin.root)
except AttributeError:
    print("AttributeError")  # AttributeError
try:
    print(cPointer.contents.kotlin.root)
except AttributeError:
    print("AttributeError")  # AttributeError
try:
    print(cPointer.contents.value.kotlin.root)
except AttributeError:
    print("AttributeError")  # AttributeError

解决方法

核心问题是没有用ctypes定义对应嵌套结构体的类型,也未指定函数返回类型,导致ctypes默认把返回的指针当成普通整数处理,无法识别结构体成员。

步骤1:定义对应C的嵌套结构体

用ctypes.Structure子类逐层映射C中的嵌套结构,成员名和类型必须和C头文件完全一致:

import ctypes

# 定义最内层的root结构体(根据实际C头文件补充成员)
class RootStruct(ctypes.Structure):
    _fields_ = [
        # 示例:如果root里有int类型成员,添加如下行
        # ("example_int", ctypes.c_int),
        # 其他成员按实际情况补充
    ]

# 定义包含root的kotlin结构体
class KotlinStruct(ctypes.Structure):
    _fields_ = [
        ("root", RootStruct)
    ]

# 定义最外层的导出符号结构体
class LibnativeExportedSymbols(ctypes.Structure):
    _fields_ = [
        ("kotlin", KotlinStruct)
    ]

步骤2:设置函数返回类型

加载DLL后,给libnative_symbols指定返回类型为结构体指针,避免ctypes默认把返回值当成整数:

libPath = "path/to/libnative.dll"
dll = ctypes.CDLL(libPath)
# 指定函数返回类型为LibnativeExportedSymbols的指针
dll.libnative_symbols.restype = ctypes.POINTER(LibnativeExportedSymbols)

步骤3:正确访问结构体成员

调用函数后,通过指针的.contents属性获取结构体实例,再逐层访问嵌套成员:

# 获取结构体指针
lib_symbols_ptr = dll.libnative_symbols()
# 逐层访问到root结构体
root_instance = lib_symbols_ptr.contents.kotlin.root
# 访问root的成员(示例)
# print(root_instance.example_int)

关键说明

  • 必须严格按照C头文件的结构定义ctypes.Structure子类,成员名、类型、嵌套层级完全对应,否则无法正确解析内存布局。
  • 一定要设置函数的restype:ctypes默认将函数返回值视为c_int,会把结构体指针转成普通整数,自然无法访问结构体成员。
  • 结构体指针通过.contents获取指向的结构体实例,之后即可用.访问嵌套成员,和C语言的->逻辑一致。

内容的提问来源于stack exchange,提问作者Marco Eckstein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:45:18