2015-08-04 16 views
6

Jak mogę przekazać wygenerowaną dynamicznie funkcję C++ jako * funcprt do API C?Howto przekazać funcptr z klasy C++ do API C?

eksportuje tego API:

DllImport void api_register_func(char *func_name, void (*funcptr)(char *, char *)); 

muszę stworzyć działają podczas wykonywania ponieważ nie wiem o tym wcześniej. Więc użyłem Klasa:

class JsFunc 
{ 
    public: 
     char * JsFuncName; 
     char * JsParameter; 

    void RunFunc(char * val1, char * val2) 
    { 
     printf("\nJsFunc.runFunc executed, JsParameter=%s passed\n",JsParameter); 
    } 
}; 

i nazwać tak:

JsFunc * jsm = new JsFunc(); 
jsm->JsFuncName = external_parameter1; 
jsm->JsParameter = external_parameter2; 
api_register_func(external_parameter1, jsm->RunFunc); 

Ale VisualStudio 2015 mówi mi:

Błąd C3867 'JsFunc :: runFunc' nie- standardowa składnia; stosowanie '&' do utworzyć wskaźnik do członkiem VJCS C: \ Users \ astrauss \ Source \ Repos \ VCJS \ VCJS \ VCJS.cpp 54

Niestety jeśli kod jest źle, nie jestem Programista C/C++, ale muszę uruchomić tę funkcję w mojej codziennej pracy. Dzięki!

+0

Czy masz dostęp do C++ 11? – Kupiakos

+3

Niestety większość tego nie ma żadnego sensu. Wygląda na to, że pytasz o rozwiązanie, zamiast pytać o problem ([XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)). Spróbuj zmienić swoje pytanie – Amit

+0

Nie możesz tego dokładnie zrobić, ponieważ RunFunc ma "ukryty" parametr 'this', o którym C nic nie wie (który posiada wskaźnik do twojego obiektu' jsm'.) Musisz znaleźć w jakiś sposób można "załadować" gdzieś adres 'jsm' –

Odpowiedz

1

Niestety, nie masz tu zbyt wielu opcji. Interfejs API:

DllImport void api_register_func(char *func_name, 
           void (*funcptr)(char *, char *)); 

udostępnia tylko wskaźnik funkcji bez kontekstu. Możesz więc przekazać darmową funkcję lub statyczną funkcję członka, ale nie masz możliwości zapewnienia funkcji członka. Jeśli miał kontekstu:

DllImport void better_api_register_func(char *func_name, 
             void *context, 
             void (*funcptr)(void *, char *, char *)); 

Następnie można napisać prosty lambda:

api_register_func(external_parameter1, 
        jsm, //context 
        [](void *ctxt, char* arg1, char* arg2) { 
         static_cast<JsFunc*>(ctxt)->runFunc(arg1, arg2); 
        }); 

a ty skutecznie przy użyciu funkcji członka, jak zwrotnego. Jednak nie jest to opcja. Zamiast utkniesz z użyciem zmiennej globalnej:

std::unique_ptr<JsFunc> the_global_func; 

który można przeznaczyć na starcie:

the_global_func.reset(new JsFunc); 
// set stuff 

a następnie użyj globalnego w lambda. Ponieważ jest globalny, nie musimy go (w rzeczywistości nie możemy) przechwytywać - co oznacza, że ​​nasza lambda może być przekształcana w wskaźnik funkcji:

api_register_func(external_paramter1, 
        [](char* arg1, char* arg2) { 
         the_global_func->runFunc(arg1, arg2); 
        }); 
+0

Wielkie dzięki! To powinno dla mnie działać. W tej chwili nie mogę go wypróbować za pomocą API, ale kompiluje :) – Andreas

+0

Barry, twój kod działa dla jednej "the_global_func". Ale nie znalazłem sposobu, aby to zrobić dla więcej niż jednego. Czy istnieje inna możliwość niż zdefiniowanie więcej niż jednego "the_global_func" (the_global_func1, the_global_func1, ...)? Próbowałem umieścić the_global_func w wektorze, ale nie mogę przekazać indeksu do api_register_func. Kiedy zmienię [] (char ... na [=] (char ... Mogę przekazać indeks, ale lambda zwraca inny typ: Jeszcze raz dziękuję! – Andreas

Powiązane problemy