2

So, i have the following use-case. Basically: I'm using templates to wrap a function of any signature in a function with the signature duk_ret_t(*)(duk_context*). However, i have encountered a problem if i try to wrap more than one function with the same signature: the returned lambdas are the same ones - the address their pointers are pointing to is the same. Here is my DukFunction class, which generates the Lambda:

class DukFunction
{
public:
    DukFunction(std::string name_item)
    {
        m_Name = name_item;
    }

    template<typename T_Return, typename ... T_Params>
    void bindFunction(T_Return(*function_item)(T_Params ...))
    {
        std::function<T_Return(T_Params ...)> proxy_func(function_item);
        duk_c_function lmb = [] (duk_context* ctx) -> duk_ret_t {
            static bool function_ran_already = false;
            static std::function<T_Return(T_Params ...)> function_item = *((std::function<T_Return(T_Params ...)>*)detail::duk_function_data);
            if(function_ran_already)
            {
                std::cout << "i ran!" << std::endl;
                return 0;
            }
            else if (function_ran_already == 0)
            {
                detail::duk_function_data = NULL;
                function_ran_already = true;
            }
        };
        rubberduk::detail::duk_function_data = (void*)&proxy_func;
        lmb(NULL);
        m_Function = duk_function_t(lmb);
    }
    ...
}

and here, in main.cpp i use the DukFunction class to bind 2 functions of the same signature.

int printSomething(int arg1, std::string arg2)
{
    return 101;
}
int printSomething2(int arg1, std::string arg2)
{
    unsigned int eeg = arg1;
    return 432 + arg1;
}
int main(int argc, char** argv)
{
    rubberduk::DukFunction df("c_print");
    rubberduk::DukFunction df2("c_print2");
    df.bindFunction(printSomething);
    df2.bindFunction(printSomething2);
    duk_c_function x = *df.getFunction().target<duk_ret_t(*)(duk_context*)>();
    std::cout << (void*)x << std::endl;
    x(NULL);
    duk_c_function x2 = *df2.getFunction().target<duk_ret_t(*)(duk_context*)>();
    std::cout << (void*)x2 << std::endl;
    x2(NULL);
    return 0;
}

As i said, i get the following result:

i ran!
0x4f4cc0
i ran!
0x4f4cc0
i ran!

As one can clearly see, the addresses of the return lambdas are the same. Im guessing this is because lambdas are generated compile-time(?), and C++ obviously only generates the bindFunction template once for both cases, since they share the same template arguments. Can anyone give me a clear answer? Is there any workaround for this, so i can achieve what i want to achieve (see above)? Thanks in advance, i'm really desperately searching for a solution to my problem, but i cant seem to find one...

tubberd
  • 540
  • 5
  • 15
  • Simply put, if more than one TU sees the definition of `DukFunction` then this is an ODR violation, so any answer would be speculation on the behavior of UB. – ildjarn Feb 21 '16 at 00:33
  • @ildjarn im sorry, what?? – tubberd Feb 21 '16 at 00:41
  • 1
    You are using lambdas, which are unique to each TU, inside inline functions. If those inline functions are compiled into multiple TUs, then you have ODR violations, and hence UB. See http://stackoverflow.com/q/34717823/636019 – ildjarn Feb 21 '16 at 00:46
  • @ildjarn oh, completely overseen that. guess youre right. in that case, i can just use a templated function, rather than a lambda. do you have a solution or hint for my problem? – tubberd Feb 21 '16 at 01:10
  • Can the downvoter explain, please?! – tubberd Feb 21 '16 at 03:13

0 Answers0