动态运行c语言,是否可以在C ++中的运行时动态创建函数?

本文介绍了一种使用C++在运行时动态编译类,并通过dlopen和GetProcAddress实现类实例化的方法。示例展示了如何在Linux环境下创建临时代码文件,编译为动态链接库,然后通过动态链接库中的maker函数创建类实例。
摘要由CSDN通过智能技术生成

下面是基于前面提到的方法的C ++运行时编译示例(将代码写入输出文件,通过LoadLibrary进行编译,通过GetProcAddress和dlsym()进行加载)。 另请参阅相关问题中的示例。 此处的区别在于,它动态地编译类而不是函数。 这是通过在要动态编译的代码中添加C样式的maker()函数来实现的。 参考文献:

[https://www.linuxjournal.com/article/3687]

[http://www.tldp.org/HOWTO/C++-dlopen/thesolution.html]

该示例仅在Linux下工作(Windows具有LoadLibrary和GetProcAddress函数),并且要求目标计算机上具有相同的编译器。

基类

#ifndef BASECLASS_H

#define BASECLASS_H

class A

{

protected:

double m_input; // or use a pointer to a larger input object

public:

virtual double f(double x) const = 0;

void init(double input) { m_input=input; }

virtual ~A() {};

};

#endif /* BASECLASS_H */

main.cpp

#include "baseclass.h"

#include // EXIT_FAILURE, etc

#include

#include

#include

#include // dynamic library loading, dlopen() etc

#include // std::shared_ptr

// compile code, instantiate class and return pointer to base class

// https://www.linuxjournal.com/article/3687

// http://www.tldp.org/HOWTO/C++-dlopen/thesolution.html

// https://stackoverflow.com/questions/11016078/

// https://stackoverflow.com/questions/10564670/

std::shared_ptr compile(const std::string& code)

{

// temporary cpp/library output files

std::string outpath="/tmp";

std::string headerfile="baseclass.h";

std::string cppfile=outpath+"/runtimecode.cpp";

std::string libfile=outpath+"/runtimecode.so";

std::string logfile=outpath+"/runtimecode.log";

std::ofstream out(cppfile.c_str(), std::ofstream::out);

// copy required header file to outpath

std::string cp_cmd="cp " + headerfile + " " + outpath;

system(cp_cmd.c_str());

// add necessary header to the code

std::string newcode = "#include \"" + headerfile + "\"\n\n"

+ code + "\n\n"

"extern \"C\" {\n"

"A* maker()\n"

"{\n"

" return (A*) new B(); \n"

"}\n"

"} // extern C\n";

// output code to file

if(out.bad()) {

std::cout << "cannot open " << cppfile << std::endl;

exit(EXIT_FAILURE);

}

out << newcode;

out.flush();

out.close();

// compile the code

std::string cmd = "g++ -Wall -Wextra " + cppfile + " -o " + libfile

+ " -O2 -shared -fPIC &> " + logfile;

int ret = system(cmd.c_str());

if(WEXITSTATUS(ret) != EXIT_SUCCESS) {

std::cout << "compilation failed, see " << logfile << std::endl;

exit(EXIT_FAILURE);

}

// load dynamic library

void* dynlib = dlopen (libfile.c_str(), RTLD_LAZY);

if(!dynlib) {

std::cerr << "error loading library:\n" << dlerror() << std::endl;

exit(EXIT_FAILURE);

}

// loading symbol from library and assign to pointer

// (to be cast to function pointer later)

void* create = dlsym(dynlib, "maker");

const char* dlsym_error=dlerror();

if(dlsym_error != NULL) {

std::cerr << "error loading symbol:\n" << dlsym_error << std::endl;

exit(EXIT_FAILURE);

}

// execute "create" function

// (casting to function pointer first)

// https://stackoverflow.com/questions/8245880/

A* a = reinterpret_cast (create)();

// cannot close dynamic lib here, because all functions of the class

// object will still refer to the library code

// dlclose(dynlib);

return std::shared_ptr(a);

}

int main(int argc, char** argv)

{

double input=2.0;

double x=5.1;

// code to be compiled at run-time

// class needs to be called B and derived from A

std::string code = "class B : public A {\n"

" double f(double x) const \n"

" {\n"

" return m_input*x;\n"

" }\n"

"};";

std::cout << "compiling.." << std::endl;

std::shared_ptr a = compile(code);

a->init(input);

std::cout << "f(" << x << ") = " << a->f(x) << std::endl;

return EXIT_SUCCESS;

}

输出

$ g++ -Wall -std=c++11 -O2 -c main.cpp -o main.o # c++11 required for std::shared_ptr

$ g++ -ldl main.o -o main

$ ./main

compiling..

f(5.1) = 10.2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值