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

如何在C程序编译阶段获取C++类的大小?

问题:在C编译阶段获取C++类的大小以实现静态分配

我开发了一个C++库,正在制作C封装供C程序员使用,目前通过裸指针实现了基础功能,具体代码如下:

相关代码

some_class.hpp

namespace AAA {
    class SomeClass{
        int some_func(int a, int b);
    };
}

c_wrapper.h

#include <stddef.h> 
typedef void* c_wrapper_some_class_t;

extern size_t const SOME_CLASS_SIZE;

c_wrapper_some_class_t* some_class_construct(void *mem, size_t size);
int some_class_some_func(c_wrapper_some_class_t *obj, int a, int b);

c_wrapper.cpp

#include <new>
#include <stddef.h>
#include "c_wrapper.h"

extern "C"
{

size_t const SOME_CLASS_SIZE = sizeof(AAA::SomeClass);

c_wrapper_some_class_t *some_class_construct(void *mem, size_t size)
{
    if (size < SOME_CLASS_SIZE || mem == nullptr )
    {
        return nullptr;
    }
    return new (mem) AAA::SomeClass; // Placement new
}

int some_class_some_func(c_wrapper_some_class_t *obj, int a, int b){
    return reinterpret_cast<AAA::SomeClass*>(obj)->some_func(a,b);
}

}

main.c

#include <stdlib.h>
#include <assert.h>
#include "c_wrapper.h"

void * mem = malloc(SOME_CLASS_SIZE);
c_wrapper_some_class_t* obj = some_class_construct(mem);
assert(obj != NULL);
int c = some_class_some_func(obj, 1,2);

目前该方案可通过动态分配正常工作,但无法在C编译时获取SomeClass的大小以实现整洁的静态分配(仅能让用户猜测足够大的空间)。我曾考虑编译c_wrapper.o后用objdump提取大小,再通过CMake模板生成自定义头文件,但库面向嵌入式平台且需要具备可移植性,因此想寻求在C程序编译阶段获取C++类大小的方法。


可行解决方案

1. 编译期生成头文件(推荐,可移植)

写一个轻量的C++辅助程序,用来生成包含类大小常量的C头文件,在构建阶段先执行该程序,再编译C代码:

步骤1:编写生成工具gen_size_header.cpp

#include <fstream>
#include "some_class.hpp"

int main() {
    std::ofstream out("some_class_c_size.h");
    out << "#ifndef SOME_CLASS_C_SIZE_H\n";
    out << "#define SOME_CLASS_C_SIZE_H\n";
    out << "#include <stddef.h>\n";
    out << "static const size_t SOME_CLASS_SIZE = " << sizeof(AAA::SomeClass) << ";\n";
    out << "#endif\n";
    return 0;
}

步骤2:在构建系统中集成(以CMake为例)

# 先编译生成工具
add_executable(gen_size_header gen_size_header.cpp)
# 运行工具生成头文件
add_custom_command(
    OUTPUT some_class_c_size.h
    COMMAND gen_size_header
    DEPENDS gen_size_header some_class.hpp
)
# 确保C代码依赖生成的头文件
add_library(c_wrapper SHARED c_wrapper.cpp some_class_c_size.h)
target_include_directories(c_wrapper PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

步骤3:C代码使用

修改c_wrapper.h,让它包含生成的头文件:

#include <stddef.h>
#include "some_class_c_size.h"

typedef void* c_wrapper_some_class_t;

c_wrapper_some_class_t* some_class_construct(void *mem, size_t size);
int some_class_some_func(c_wrapper_some_class_t *obj, int a, int b);

之后C代码就能直接在编译时用SOME_CLASS_SIZE做静态分配:

// 静态分配
char some_class_storage[SOME_CLASS_SIZE];
c_wrapper_some_class_t* obj = some_class_construct(some_class_storage, SOME_CLASS_SIZE);

2. 利用C++条件编译导出常量(半编译期,纯C需链接)

如果不想生成额外头文件,可以通过条件编译让C++编译器计算大小,同时给C编译器提供外部常量:

修改头文件c_wrapper.h

#include <stddef.h>

#ifdef __cplusplus
#include "some_class.hpp"
constexpr size_t SOME_CLASS_SIZE = sizeof(AAA::SomeClass);
#else
extern const size_t SOME_CLASS_SIZE;
#endif

typedef void* c_wrapper_some_class_t;

c_wrapper_some_class_t* some_class_construct(void *mem, size_t size);
int some_class_some_func(c_wrapper_some_class_t *obj, int a, int b);

在c_wrapper.cpp中定义常量

#include <new>
#include "c_wrapper.h"

extern "C" {
const size_t SOME_CLASS_SIZE = sizeof(AAA::SomeClass);

// 其余函数保持不变
}

这种方式下,C++代码能在编译期拿到常量值,但纯C代码只能在链接时解析,无法用该常量做静态数组的大小(因为C要求静态数组大小是编译期常量),因此更适合动态分配场景,静态分配还是推荐第一种方法。

3. 封装静态分配接口(简化用户操作)

结合第一种方法,在C封装中直接提供静态分配的辅助宏和函数,降低用户使用成本:

在c_wrapper.h中添加

#include "some_class_c_size.h"

// 定义静态存储的宏
#define SOME_CLASS_STATIC_STORAGE(var_name) char var_name[SOME_CLASS_SIZE]

// 初始化静态存储的封装函数
c_wrapper_some_class_t* some_class_construct_static(char *static_mem);

// 其余原有声明...

在c_wrapper.cpp中实现

extern "C" {
// ...原有函数...

c_wrapper_some_class_t* some_class_construct_static(char *static_mem) {
    // 内部已经确保大小足够,无需用户传入
    return some_class_construct(static_mem, SOME_CLASS_SIZE);
}
}

用户使用示例

SOME_CLASS_STATIC_STORAGE(my_class_mem);
c_wrapper_some_class_t* obj = some_class_construct_static(my_class_mem);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:54:52