I tried to create a function which is returning a vector in C++. But when it built to dll, the function name seems to be mangled.
I tried to use the extern C but the problem is return type vector cannot support if I use extern C
Error : C Linkage function cannot return C++ class std:: Vector
Below is the code I am using
class __declspec(dllexport) TestClass
{
public:
string sClassName;
string sName;
string sDescription;
};
extern "C"
{
vector<TestClass> __declspec(dllexport) GetInfoList();
}
We see it is not problem with easy solution. Here's an involved solution. Use a non-mangled name (extern "C") with GetProcAddress to access a special function in the higher level DLL. . Define all the functions you want to call, as virtuals, in an abstract base class. Call that function above to retrieve the pointer P to a lazily instantiated concrete class with virtuals overriden. Invoke desired method through the pointer P.
vector is C++ type and so cannot be directly given under extern "C". Give the function inside a class and export the class as C Type.
extern "C"
{
class __declspec(dllexport) ClassToExport
{
vector<TestClass> GetInfoList();
};
}
Now use this class object to axcess the function.
Related
ultimately my goal is to write a Qt class(my class inherits from QObject and uses Q_OBJECT macro), then build a dll from it. then in python use ctype to access that dll.
when I write the dll normally, method names get mangled so I can't use them directly. instead I have to use getattr which I don't want to use(because others may need to use the dll and I don't want them to get confused).
anyway I read that to stop name mangle I need to use extern "C"
so far I tried these:
extern "C"
{
class MyClass::public QObject
{
Q_OBJECT
public:
void SomeFunction(int Parameter);
}
}
this one does not build because in Q_OBJECT macro templates are used and I get "templates cannot be declared to have 'C' linkage" error.
i tried:
extern "C" typedef void SomeFunction_t(int parameter);
class MyClass::public QObject
{
Q_OBJECT
public:
SomeFunction_t SomeFunction;
}
this one compiled but still SomeFunction name was mangled;
also I can't use extern "C" directly before method declaration because it is inside of class.
so how can I prevent name mangling here?
I'm going to hazard a guess this might be failing because of this construct:
extern "C"
{
class I_AM_A_CPLUSPLUS_CONCEPT {};
}
Anyhow, this is solvable, but requires a little rethink. To expose the class to C, you will have to jump through a couple of hoops here.
// the C++
class MyClass : public QObject
{
Q_OBJECT
public:
void SomeFunction(int Parameter);
};
extern "C" MyClass* MyClass_new() {
return new MyClass;
}
extern "C" void MyClass_delete(MyClass* c) {
delete c;
}
extern "C" void MyClass_SomeFunction(MyClass* c, int p) {
c->SomeFunction(p);
}
'MyClass' will be mangled into a C++ name, and there isn't really any way to expose 'SomeFunction' as a member of MyClass, without using name mangling.
C-Name mangling in the above example will simply expose:
MyClass_new, MyClass_delete, and MyClass_SomeFunction as the symbol names. (i.e. devoid of the function argument types, return type, calling convention, owning class, etc... which is what C++ name mangling will add in).
Just treat MyClass as an opaque pointer, and C code should be happy enough with that. Short of resorting to pybind/boost::python (which clearly don't really work with DLL's cleanly!!), there aren't really any other nice ways to bind in a C++ object to c code.
I want to provide a callback function for code written in Haskell (GHC). It uses GCC C-compiler-like function types to export/import functionality and interoperate at runtime with my code.
I have to provide a callback function, which in fact accept this pointer to the class and just call its method:
struct C
{
int f(int i) { ; }
static int f_callback(void * self, int i)
{
static_cast< C * >(self)->f(i);
}
};
Logically f_callback is a part of class C, so I placed it into the corresponding namespace scope.
But I worry about should I use extern "C" language specification (calling convention is matters here, not name mangling)? It is possible to declare and define extern "C" function in plain namespace, there are a couple of special rules for extern "C" functions defined with the same name in different namespaces, but there is no distinction between namespace of class scope and simple namespace one.
Is it possible to define static extern "C" function into class scope?
The external callback is by design not linked to a specific class.
Making it a static class member is perhaps nice according to the internals of your code, but it misrepresents the reality.
I'd therefore advise to make it an independent extern "C" function. This avoids misunderstanding and highlights assumptions (for example that self is assumed to be a C but could in reality be something else). If f() is public, all this will be very clean. If it would be private, you'd need to make your callback a friend and this tight coupling would be again highlighted.
The wrapper alternative would just add a redundant middleman to come to the same result.
I'm writing a dll, which exports a function
extern "C"
__declspec(dllexport)
std::list<string> create() {
return std::list<string>();
}
the compiler complains:
error C2526: 'create' : C linkage function cannot return C++ class 'std::list<_Ty>'
if I remove the extern "C", the function name exported would be:
?create##YA?AV?$list#PAUanalyzer##V?$allocator#PAUanalyzer###std###std##XZ
I want the name to be clean, so I added extern "C", now it conflicts
Any other way can get a clean function name?
Thanks.
When you say extern "C" you tell the compiler to create a function that can be called from other languages than C++ (most notably C). However, no other language than C++ have std::list, so it can not create such a function because the return type is part of the function signature in C++. And if you don't create a function which has C-compatible return type (or arguments) you can not create an extern "C" function.
If you're going to use the DLL from a C++ program there is no need for the extern "C" part. The C++ compiler and linker will be able to handle the mangled name without problems anyway.
You can return a pointer instead of the object.
extern "C" __declspec(dllexport) std::list<std::string>* createAllocated()
{
return new std::list<std::string>();
}
Due to the nature of C++, the caller will need to have the compatible ABIs.
I'm trying to call a kernel wrapper foo from a C++ class. I've tried to do as suggested here below:
// In CPP.h:
class cls {
extern "C" inline void foo();
}
// In Kernels.cu:
#include "CPP.h"
extern "C" inline void cls::foo() {
// call kernels here
}
but this has not worked - I get a compiler errors:
CPP.h: invalid storage class for a class member
CPP.h: "cls::foo" was referenced but not defined
Kernels.cu: label "cls" was declared but never referenced
What's going wrong?
You shouldn't mark a class method with extern "C".
Make a wrapper non-member function with extern "C" specifier, and let this function call your class's method (you will need to specify an instance also).
How to create some class from dll(constructor in dll)?(C++)
or how to dynamically load class from dll?
You need to declare your class using the __declspec(dllexport) keyword when building the DLL. When using the DLL, the class needs to be declared with __declspec(dllimport):
#ifdef COMPILING_DLL
#define DECLSPEC_CLASS __declspec(dllexport)
#else
#define DECLSPEC_CLASS __declspec(dllimport)
#endif
class DECLSPEC_CLASS MyClass
{
...
}
When the DLL is compiled, you should add -DCOMPILING_DLL to the list of defines.
When using the class, you must statically link with the DLL, i.e. pass the import library mydll.lib to the main program.
If you want to load the DLL at runtime, you need to have a C-function in the DLL which creates a object and returns it for you. There is no way to lookup a constructor dynamically in a DLL (using GetProcAddress()).
Answering your question strictly, you need to add an extern "C" function that returns the result of the constructor:
extern "C" foo* __declspec(dllexport) new_foo(int x) {
return new foo(x);
}
Then in your source you can use GetProcAddr on "new_foo" to call the function.
You will need to export a function from the DLL that calls on to the constructor and returns the new object.
Try to avoid using concrete C++ types as function parameters; the idea of DLLs is that you can independently update them, but an upgraded compiler may lay out std::string differently, causing incompatibility at runtime.
This is what is at the root of COM, for example - a limited type system and a standard exported function for getting instances of objects.
Instead of exporting every method of the class using __declspec, you can also rely on the fact that the compiler can invoke virtual functions via the vtable, so for example:
//note: no __declspec
class IPublicInterface
{
virtual ~IPublicInterface() = 0;
virtual void SomeMethod() = 0;
};
//note: no __declspec
class SomeClass : IPublicInterface
{
virtual ~SomeClass() { ... }
virtual void SomeMethod() { ... }
};
//note: this is the only method which needs to be exported from the DLL
IPublicInterface* createSomeClass()
{
return new SomeClass();
}