具有通用类型函数的动态库[C ]
Dynamic Libraries with generic type functions [c++]
最后一天我想在C 中进行此操作:
假设我有一个函数foo(arg1, arg2)
,一个客户端和一台服务器。 arg1
可以是任何类型,arg2
可以是任何类型,foo
可以返回任何类型的数据。函数foo
总是有两个参数。
我希望客户作为输入此功能(例如):
foo(arg1,arg2){
if(arg1<arg2){
return 1;
}else{
return 5.3;
}
return 0;
}
,然后将此功能在服务器上传输和执行。
我试图用模板内部使用此功能构建动态库。但是,extern "C"
不支持模板。我尝试导出的库是:
#include < iostream >
extern "C" {
template < typename N >
N testFunc(char * arg) {
N test = 5;
std::cout << "Executed| arg is:" << arg << std::endl;
return test;
}
}
然后我尝试使用以下命令进行编译:
g -wall -fpic -c lib.cpp
g -shared -o lib.so lib.o
所以有什么想法我该如何实施?
我知道这不是安全的,但仅出于教育目的。
如果我们做出一些简化的假设,那还不错:让我们想象一下,您要发送和执行的函数远程执行不进行任何参数,并且返回没有值。然后您可以执行以下(下面的工作示例):
-
将源字符串发送到服务器。
-
在服务器上,调用gcc来编译字符串,就像您在问题中所描述的一样。
-
加载共享对象,然后调用函数。
现在,可以将其扩展到您想要的情况,并进行更多的工作:当客户端发送功能时,服务器会保留该功能以供以后使用。后来,客户端将一个字符串发送到该函数(包括参数)作为C 字符串的字符串。服务器将调用字符串附加到功能字符串的底部,然后编译并运行整个字符串,如下所示。在此模型中,函数代码确实可以是模板,并且呼叫字符串可以包含任何类型扣除可以工作的参数。缺点是您每次都会编译该功能。根据函数的运行时间的微不足道或时间密集型,这可能对您来说可能不是问题。当然,有很多方法可以更好地做这一切,但我希望这是您的起点。
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstdio>
#include <string>
#include <cassert>
#include <dlfcn.h>
// Compile this with: g++ test.cpp -ldl
// Utility: check various calls below and bail out if bad.
int check(int line, int ret, int err = -1)
{
if (ret == err)
{
fprintf(stderr, "on line %d: ", line);
perror("");
abort();
}
return ret;
}
#define CHECK(X, ...) check(__LINE__, X, ##__VA_ARGS__)
// Common ipv4 address used by both client and server.
struct sockaddr_in addr{};
// This runs the client's part.
int client_main()
{
usleep(100000); // delay to give the server a chance to start.
// Connect to the server
auto sock = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(connect(sock, (sockaddr*) &addr, sizeof(addr)));
// This is the function to be remotely executed.
std::string msg = R"(
#include <cstdio>
template <class T>
void remote_function(T arg1, T arg2)
{
if (arg1 < arg2)
printf("lessn");
else
printf("moren");
}
// ---- portion below can be sent separately and appended by server later -----
extern "C" void runit()
{
remote_function(100, 1000);
}
)";
// Send the source
write(sock, msg.c_str(), msg.size());
close(sock);
// Client is done
return 0;
}
// This is the server's part.
int server_main()
{
// Listen for incoming connection from client
auto sock = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(bind(sock, (sockaddr*) &addr, sizeof(addr)));
CHECK(listen(sock, 1));
struct sockaddr_in peer;
socklen_t peer_sz = sizeof(peer);
auto conn = CHECK(accept(sock, (sockaddr*) &peer, &peer_sz));
// Read the source code from the client
constexpr size_t maxSize = 1024 * 1024;
std::string source(maxSize, 0);
auto sz = CHECK(read(conn, &source[0], maxSize));
source.resize(sz);
printf("server got:%sn", source.c_str());
// Compile it
auto gcc = popen("/usr/bin/g++ -o /tmp/_test.so -fPIC -shared -xc++ -", "w");
assert(gcc);
CHECK(fwrite(&source[0], 1, source.size(), gcc));
auto ret = CHECK(pclose(gcc));
if (ret == 0)
printf("compiled!n");
else
abort();
// Load the compiled library
auto lib = dlopen("/tmp/_test.so", RTLD_LOCAL | RTLD_NOW);
assert(lib);
// Run the function
void (*fun)();
* (void**) &fun = dlsym(lib, "runit");
assert(fun);
(*fun)();
// Finished
dlclose(lib);
return 0;
}
int main()
{
// Set up address both client and server use to communicate.
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(3333); // some arbitrary port.
if (fork())
return server_main();
else
return client_main();
}
将两个对象发送到服务器是不够的。您还必须告诉服务器如何比较两个对象。
例如,假设我有一个客户端,您有服务器。假设我在客户端上定义了Country
类型。假设netherlands < germany
表达式评估为true,因为我已经定义了 operator<(const Country&, const Country&)
比较土地区域。荷兰覆盖的土地比德国少,所以netherlands < germany == true
,对吗?
麻烦是您的服务器不知道Country
是什么,也不知道如何比较该类型的两个对象。
即使您的服务器确实知道Country
,我总是可以想出服务器不知道的另一种类型。因此,除非我误解了您的问题,否则我不认为有一种直接的方法来做您想做的事情。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在动态数组上使用搜索函数
- 通过构造函数动态确定类实现
- 对具有动态分配的内存和析构函数的类对象的引用
- 调用析构函数以释放动态分配的内存
- 为什么类和 main() 函数中也有动态内存分配
- 具有自定义构造函数 (C++) 的类型的动态数组分配
- 运行时的动态函数解析
- 在没有动态内存的世界中,我是否需要虚拟析构函数?
- 创建类类型的动态分配数组,其中类不得具有默认构造函数
- 编译时动态函数调用
- C 中的动态函数参数,可能
- 在不模板的情况下计算另一个类的动态函数指针
- C++:传递动态函数和存储函数
- 一个可以使用动态函数交换的函数
- 动态函数来调用函数
- c++中用于Callback / RPC的动态函数参数
- 运行时的动态函数调用(va_list)
- 如何在c++ 11和c++ 14中实现动态函数调用