簡體   English   中英

C ++試圖從std :: function獲取函數地址

[英]C++ trying to get function address from a std::function

我試圖從std :: function中找到函數的地址。

第一個解決方案是:

size_t getAddress(std::function<void (void)> function) {
    typedef void (fnType)(void);
    fnType ** fnPointer = function.target<fnType *>();
    return (size_t) *fnPointer;
}

但這只適用於帶有(void())簽名的函數,因為我需要簽名為(void(Type&))的函數,我試圖做

template<typename T>
size_t getAddress(std::function<void (T &)> function) {
    typedef void (fnType)(T &);
    fnType ** fnPointer = function.target<fnType *>();
    return (size_t) *fnPointer;
}

我得到“錯誤 - 預期”('用於函數式轉換或類型構造“

更新:有沒有辦法捕獲成員類地址? 對於我正在使用的班級成員:

template<typename Clazz, typename Return, typename ...Arguments>
size_t getMemberAddress(std::function<Return (Clazz::*)(Arguments...)> & executor) {
    typedef Return (Clazz::*fnType)(Arguments...);
    fnType ** fnPointer = executor.template target<fnType *>();
    if (fnPointer != nullptr) {
        return (size_t) * fnPointer;
    }
    return 0;
}

更新:捕獲lambda我正在使用

template <typename Function>
struct function_traits
    : public function_traits<decltype(&Function::operator())> {
};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
    typedef ReturnType (*pointer)(Args...);
    typedef std::function<ReturnType(Args...)> function;
};

template <typename Function>
typename function_traits<Function>::function
to_function (Function & lambda) {
    return static_cast<typename function_traits<Function>::function>(lambda);
}

template <typename Lambda>
size_t getAddress(Lambda lambda) {
    auto function = new decltype(to_function(lambda))(to_function(lambda));
    void * func = static_cast<void *>(function);
    return (size_t)func;
}

std::cout << getAddress([] { std::cout << "Hello" << std::endl;}) << std::endl;

調用target時需要使用template關鍵字:

#include <functional>
#include <iostream>

template<typename T>
size_t getAddress(std::function<void (T &)> f) {
    typedef void (fnType)(T &);
    fnType ** fnPointer = f.template target<fnType*>();
    return (size_t) *fnPointer;
}

void foo(int& a) {
    a = 0;
}

int main() {
    std::function<void(int&)> f = &foo;
    std::cout << (size_t)&foo << std::endl << getAddress(f) << std::endl;
    return 0;
}

提示:當您遇到C ++語法問題時,我建議您使用clang++來編譯代碼。 如果你如何編寫代碼,它通常會指向你的寫入方向來修復錯誤(當它能夠弄清楚你在做什么時)。

我還建議您使用可變參數模板使您的函數更通用:

template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
    typedef T(fnType)(U...);
    fnType ** fnPointer = f.template target<fnType*>();
    return (size_t) *fnPointer;
}

std::function只是一個對象,雖然偽裝成非對象。 因此,我們可以獲取此對象的地址,這對於副本等是不變的。

要獲得指針,我們需要一點點投射。 例如,給定函數f1 ,我們可以通過執行以下操作來打印隱式指針:

std::cout << "f1: " << *(long *)(char *)&f1 << std::endl;

這樣做是:

  • 取f1的地址。 f1本身是一個指向函數對象的指針,雖然偽裝成一個原語
    • 所以這個地址是指向函數指針的指針
    • 我們想要的是該函數的底層指針
  • 將指向指針的指針轉換為指向char的指針
  • 從而指向long
  • 現在,假設指針大小為long s,我們可以將此指針變為long,並獲取與函數對象關聯的基礎地址。

給定兩個std::function<void()> s f1f2 ,我們可以這樣做:

std::cout << "f1: " << *(long *)(char *)&f1 << std::endl;
std::cout << "f2: " << *(long *)(char *)&f2 << std::endl;

std::function<void()> f1copy = f1;
std::cout << "\nafter copy f1 into f1copy:" << std::endl;
std::cout << "addresses of f1 and f1copy differ: " << &f1 << " " << &f1copy << std::endl;
std::cout << "but underlying pointers identical: " <<
    *(long *)(char *)&f1 << " " << *(long *)(char *)(&f1copy) << std::endl;

std::cout << "\n after assign f2 to f1copy" << std::endl;
f1copy = f2;
std::cout << "now the underlying pointer of f1copy matches f2's:" << std::endl;
std::cout <<
    *(long *)(char *)&f2 << " " << *(long *)(char *)&f1copy << std::endl;

示例輸出:

f1: 4439003784
f2: 4439003912

after copy f1 into f1copy:
addresses of f1 and f1copy differ: 0x7fff572ab970 0x7fff572ab910
but underlying pointers identical: 4439003784 4439003784

 after assign f2 to f1copy
now the underlying pointer of f1copy matches f2's:
4439003912 4439003912

暫無
暫無

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

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