2

In a C++ project I am loading a .so with dlopen and dlsym. The .so is compiled from C source and all functions have C linkages.

The only part I am not able to figure out is how do I cast the resulting pointer to an extern "C" function so that the actual call site uses the appropriate linkage.

I know one of the main difference is the name mangling and I don't have to worry about that because I am using the unmangled name to find the function with dlsym.

But my understanding is there are other aspects of the linkage which could be a mismatch (I am thinking of exception handling, different ABI?).

I have tried -

 extern "C" void (*foo) (void) = (void (*) (void)) dlsym(handle, "foo"); 

But the compiler doesn't like extern "C" for local variables. What is the right way to call functions loaded with dlsym? Or should I not have to worry about linkages?

Edit: To further clarify the question, I need to compute the function pointer types based on some template parameters which makes this harder and after the discussions in the answers and comments it is currently not possible to do this (the standards are being adjusted to allow this). The current accepted answer correctly answers the question asked.

10
  • As the compiler doesn't let you use this modifier for functors, it is safe to not use this modifier for functors. Commented Apr 8, 2022 at 17:12
  • It is obvious, a local variable does not have the external linkage, thus the extern "C" is not applicable to a local variable. Commented Apr 8, 2022 at 17:41
  • 1
    @273K is it possible that the C and C++ ABIs are different and the compiler needs to know to use the C ABI when calling this function? Commented Apr 8, 2022 at 17:46
  • @user253751 Honestly I do not understand your question. ABI is for a linker, not for a compiler. extern "C" just directs a compiler how to assign an exported name to an object. Perhaps you confused extern "C" and calling convention. Commented Apr 8, 2022 at 18:02
  • 1
    @273K compilers certainly care about ABIs (calling conventions) Commented Apr 8, 2022 at 18:07

1 Answer 1

2

Introduce a typedef first:

extern "C" typedef void (*verb)(); void f() { const auto foo=(verb)dlsym(handle, "foo"); } 
Sign up to request clarification or add additional context in comments.

7 Comments

I was thinking about the same way. Is it possible to do such a typedef inside a class? Basically I am trying to write a function with templates that accepts a function pointer and returns another function pointer whose type depends on the input function pointer. With variadic templates I am able to construct the return type, but how do I add extern to it?
Can I wrap the function in a class and have the typedef inside the class? From what I read, the extern "C" is ignored for functions inside classes. Would it also be ignored for typedefs inside classes?
My current signature looks like this - template <typename FT> auto load(FT f) -> typename type_creator<FT>::type;
@AjayBrahmakshatriya: extern "C" {…} applies to function types expressed in classes, though not to member functions themselves. The problem is that, due to some really bad wording, it is taken to be forbidden to declare a template inside, which makes it difficult or impossible to compute a type with C linkage.
So is it right to say that the standard does not allow computing extern "C" function pointer types? Also thanks for the reference.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.