从大型C++库生成C可执行文件时如何创建和链接

dbf7pr2w  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(110)

我是c初学者,C稍微高级一点,这是我第一次使用make
我有一个大型C
库(由第三方编写,需要集成到C管道中),我希望从C调用此库。为了从C调用C库,我有3个文件:.cpp文件,其实现对具有C兼容数据类型的C库的调用; .h C兼容头文件,其将C实现函数链接到C;以及.c文件,其具有main()函数,该main()函数调用具有C适当数据类型的C函数。
头文件(random_forest.h):

#ifndef RANDOMFOREST_H_
#define RANDOMFOREST_H_

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

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

// opaque forward declared struct
struct random_forest_model;

// pointer to struct used by C code
typedef struct random_forest_model* random_forest_model_t;

random_forest_model_t random_forest_new(const char* model_file_path);

void random_forest_free(random_forest_model_t random_forest_model);

uint8_t *classify(
    random_forest_model_t random_forest_model,
    const double* independentVariableData,
    const double* dependentVariableData,
    const size_t numberRows,
    const size_t numberColumns,
    const char** independentVariableNames
);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* RANDOMFOREST_H_ */

在我的random_forest.cpp文件中:

#include <memory.h>
#include "/src/random_forest.h"
#include "/src/rf/src/Forest.h"
#include "/src/rf/src/globals.h"
#include "/src/rf/src/ForestClassificationPrediction.h"
#include "/src/rf/src/utility.h"

using namespace rf; /* comes from Forest.h file */

struct random_forest_model {
  std::unique_ptr<rf::Forest> forest;
  std::string model_file_path;
}

namespace {
    std::unique_ptr<rf::Forest> random_forest_acquire(const char* model_file_path) {
        try {
            std::unique_ptr<rf::Forest> forest = make_unique<ForestClassificationPrediction>();
            forest->InitPredictionModelCpp(model_file_path);

            return forest;
        } catch(...) {
            return nullptr;
        }
    }
} /* anonymous namespace */

random_forest_model_t random_forest_new(const char* model_file_path) {
    try {
        auto forest = random_forest_acquire(model_file_path);
        return new random_forest_model{std::move(forest), model_file_path};
    } catch (...) {
        return nullptr;
    }
}

void random_forest_free(random_forest_model_t random_forest_model) {
    delete random_forest_model;
}

uint8_t* classify(
        ranger_random_forest_model_t ranger_random_forest_model,
        const double* independentVariableData,
        const double* dependentVariableData,
        const size_t numberRows,
        const size_t numberColumns,
        const char** independentVariableNames
) {
    try {
        /* bunch of stuff here to convert data and run classification */
    } catch(...) {
        return nullptr;
    }
}

然后在我的random_forest_implement.c文件中:

#include "/src/random_forest.h"

int main() {
    const char model_file_path[] = "path/to/model";
 
    random_forest_model_t random_forest = random_forest_new(model_file_path);

    /* 
    some code here to ingest a data file - outputting the data for random_forest_classify
    yielding: X, y, numberRows, numberColumns, varNames 
    */

    uint8_t *classes = classify(
        random_forest, X, y, numberRows, numberColumns, varNames
    );

    random_forest_free(random_forest);

    free(X);
    free(y);
    free(varNames);
    free(classes);

    return EXIT_SUCCESS;
}

这是一个非常冗长的方法来询问如何将这个程序编译成一个可执行文件。我试着用下面的make文件进行编译:

CC ?= gcc
CP ?= g++

random_forest_implement: random_forest_implement.o random_forest.o
    $(CP) -o random_forest_implement random_forest_implement.o random_forest.o

random_forest.o: random_forest.cpp random_forest.h
    $(CP) -c random_forest.cpp

random_forest_implement.o: random_forest_implement.c random_forest.h
    $(CC) -c random_forest_implement.c random_forest.h

clean:
    $(RM) *.o random_forest

当我尝试创建这个(make -f random_forest_make.mk)时,我得到了三行显示(?)成功的代码,并且收到了很多关于undefined reference的错误,例如:

cc -c random_forest.c random_forest.h
g++ -c random_forest.cpp
g++ -o random_forest_implement random_forest_implement.o random_forest.o
/usr/bin/ld: random_forest.o: in function `(anonymous namespace)::random_forest_acquire(char const*)':
random_forest.cpp:(.text+0x44f): undefined reference to `rf::Forest::InitPredictionModelCpp(<bunch of args necessary to method>)

我不完全确定接下来该怎么做,但是我怀疑我没有正确编译所有的东西。正如你所看到的,我的random_forest.cpp文件依赖于几个文件。我需要编译每一个文件吗?以及它们的依赖关系?有没有一个最好的/有效的方法可以做到这一点?还是需要编写一个make文件,为/src/rf/src/目录中的每个.cpp文件生成一个对象文件?

ozxc1zmp

ozxc1zmp1#

不能生成包含C源代码的C可执行文件。只有包含任何C代码时,才能创建C可执行文件。出于兼容性原因,C支持链接C源模块,但C编译器不是为链接C模块而设计的(C和C之间不存在向后兼容性,C是以前创建的)
因此,您只能使用c编译器链接C与C源代码的混合(即使main是在C源文件中定义的),因为这个动作会使C编译器在C模式下调用链接器,链接C/C模块,调用C标准库模块和运行时。C++可执行文件的内存布局比简单的纯C程序的布局更复杂

相关问题