簡體   English   中英

在不知道返回類型的情況下,通過其地址調用C ++中的函數

[英]Call a function in C++ by its address without knowing the return type

我想通過它的地址從C ++ dll調用C函數。

我知道如何在這個單獨的問題中知道返回類型的地方: 在c / c ++中通過內存中的地址調用函數

但是,如果我不知道返回類型,我該怎么辦? 我試過“typedef auto”,但似乎你不能像那樣使用auto。

如果返回的類型確實是未知的或無關緊要,你可以在函數定義中使用void ,或者如果它是任何指針你可以使用void * ,但如果函數是在C編碼的DLL中,你會在C ++代碼中使用它,然后您可以利用和共享C代碼中定義的幾乎所有類型,因為C ++它是C的超集。

也就是說,我准備了一個小例子,其中一個名為PyObject的結構在C和C ++代碼中共享。

要做到這一點,最好使用共享類型/定義創建標頭:

#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函數返回一個大聚合(例如struct)時忽略返回類型,這不是一個好主意,因為C函數期望調用者已經有保留堆棧空間來存儲返回的聚合,但是如果調用者將函數視為void或其他任何東西,則編譯器將不會保留該空間,從而導致不可預測的影響(可能以Segmentation fault錯誤結束)。

為了避免這種情況,最好在C和C ++代碼(或公共頭文件)中定義正確的類型,尤其是當C函數返回聚合時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM