在不知道 return 类型的情况下通过地址调用 C++ 中的函数
Call a function in C++ by its address without knowing the return type
我想通过 C++ dll 的地址调用 C 函数。
我知道如何从这个单独的问题中知道 return 类型:Calling a function through its address in memory in c / c++.
但是,如果我不知道 return 类型,我该怎么办?我已经试过了 "typedef auto",但你似乎不能那样使用 auto。
如果 returning 类型确实未知或无关紧要,您可以在函数定义中使用 void
,或者如果它是任何指针,您可以使用 void *
, 但如果该函数在 C 编码的 DLL 中,并且您将在 C++ 代码中使用它,那么您可以利用和共享 C 代码中定义的几乎所有类型,因为 C++ 是 C 的超集。
也就是说,我准备了一个小示例,其中包含一个在 C 和 C++ 代码中共享的名为 PyObject
的结构。
为此,最好使用共享 types/definitions:
创建一个 header
#ifndef PYOBJECT_DLL_H
#define PYOBJECT_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
// Common structure definition
typedef struct PyObject{
int field1;
char *field2;
} PyObject;
// Public function pointer type declaration
typedef PyObject *(*__stdcall getPyObject_t)(int arg1, const char *arg2);
#ifdef __cplusplus
}
#endif
#endif // PYOBJECT_DLL_H
假设带有导出函数的 C 代码类似于:
#include "pyobject.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) PyObject * getPyObject(int arg1, char *arg2);
PyObject *getPyObject(int arg1, char *arg2){
PyObject *obj = (PyObject *)malloc(sizeof(PyObject));
obj->field1 = arg1;
obj->field2 = arg2;
return obj;
}
最终,使用库中创建的函数和数据的 C++ 代码将是:
#include "pyobject.h"
#include <iostream>
#include <windows.h>
int main() {
HINSTANCE dll = LoadLibrary("pyobject.dll");
if (dll == NULL) {
std::cerr << "Cannot open pyobject.dll. Error: " << GetLastError() << "\n";
return 1;
}
getPyObject_t getPyObject = (getPyObject_t) GetProcAddress(dll, "getPyObject");
if (getPyObject == NULL) {
std::cerr << "Cannot locate 'getPyObject' function in dll. Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 2;
}
PyObject *obj = getPyObject(3, "test");
std::cout << "PyObject == { field1: " << obj->field1 << ", field2: \"" << obj->field2 << "\"}\n";
FreeLibrary(dll);
return 0;
}
编辑
正如 @raymondchen 在他的评论中指出的那样,当 C 函数 return 是一个大聚合(例如结构)时忽略 return 类型这不是一个好主意,因为 C 函数期望调用者已经保留堆栈 space 来存储 returned 聚合,但是如果调用者将函数视为 void
或其他任何东西,那么编译器将不会保留 space,造成不可预测的影响(可能以 Segmentation fault 错误结束)。
为避免这种情况,最好在 C 和 C++ 代码中(或在通用 header 中)定义正确的类型,尤其是当 C 函数 return 是聚合时。
我想通过 C++ dll 的地址调用 C 函数。
我知道如何从这个单独的问题中知道 return 类型:Calling a function through its address in memory in c / c++.
但是,如果我不知道 return 类型,我该怎么办?我已经试过了 "typedef auto",但你似乎不能那样使用 auto。
如果 returning 类型确实未知或无关紧要,您可以在函数定义中使用 void
,或者如果它是任何指针,您可以使用 void *
, 但如果该函数在 C 编码的 DLL 中,并且您将在 C++ 代码中使用它,那么您可以利用和共享 C 代码中定义的几乎所有类型,因为 C++ 是 C 的超集。
也就是说,我准备了一个小示例,其中包含一个在 C 和 C++ 代码中共享的名为 PyObject
的结构。
为此,最好使用共享 types/definitions:
创建一个 header#ifndef PYOBJECT_DLL_H
#define PYOBJECT_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
// Common structure definition
typedef struct PyObject{
int field1;
char *field2;
} PyObject;
// Public function pointer type declaration
typedef PyObject *(*__stdcall getPyObject_t)(int arg1, const char *arg2);
#ifdef __cplusplus
}
#endif
#endif // PYOBJECT_DLL_H
假设带有导出函数的 C 代码类似于:
#include "pyobject.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) PyObject * getPyObject(int arg1, char *arg2);
PyObject *getPyObject(int arg1, char *arg2){
PyObject *obj = (PyObject *)malloc(sizeof(PyObject));
obj->field1 = arg1;
obj->field2 = arg2;
return obj;
}
最终,使用库中创建的函数和数据的 C++ 代码将是:
#include "pyobject.h"
#include <iostream>
#include <windows.h>
int main() {
HINSTANCE dll = LoadLibrary("pyobject.dll");
if (dll == NULL) {
std::cerr << "Cannot open pyobject.dll. Error: " << GetLastError() << "\n";
return 1;
}
getPyObject_t getPyObject = (getPyObject_t) GetProcAddress(dll, "getPyObject");
if (getPyObject == NULL) {
std::cerr << "Cannot locate 'getPyObject' function in dll. Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 2;
}
PyObject *obj = getPyObject(3, "test");
std::cout << "PyObject == { field1: " << obj->field1 << ", field2: \"" << obj->field2 << "\"}\n";
FreeLibrary(dll);
return 0;
}
编辑
正如 @raymondchen 在他的评论中指出的那样,当 C 函数 return 是一个大聚合(例如结构)时忽略 return 类型这不是一个好主意,因为 C 函数期望调用者已经保留堆栈 space 来存储 returned 聚合,但是如果调用者将函数视为 void
或其他任何东西,那么编译器将不会保留 space,造成不可预测的影响(可能以 Segmentation fault 错误结束)。
为避免这种情况,最好在 C 和 C++ 代码中(或在通用 header 中)定义正确的类型,尤其是当 C 函数 return 是聚合时。