We have a big, old C++ application with a lot of legacy code and a few external libraries written in C. These libraries are very rarely updated - only if we find a bug and the vendor supplies a patch. This happened last week with one library, and upon integrating the new version we found out that if we don't modify the library locally (which we apparently did with the last version) our build breaks with this error message:
non-local function ‘static E* MyCls::myFct(<anonymous struct>*)’ uses anonymous type
This is due to the library declaring a number of handle types like this:
#define _Opaque struct {unsigned long x;} *
typedef _Opaque Handle;
typedef _Opaque Request;
which we use on our side in some classes' function signatures:
class MyCls {
public:
static void* myFct(Handle handle);
...
}
This produces the error above because the compiler can't create a proper name-mangled name for the function(s) as the _Opaque struct has no name.
Our current workaround for this is to patch the library header file, explicitly giving the struct a name:
//#define _Opaque struct {unsigned long x;} * //Replaced by typedef below!
typedef struct __Opaque {unsigned long x;} * _Opaque;
This is obviously bad because we don't want to touch the library if possible. Another even worse option would be to convert the types to void*
in all function signatures and cast them back to their respective types. And there's the worst option to rewrite every affected function in pure C...
So, my question is: Is there any better option than patching the library? Is there an easy solution I am overlooking? What would be the best way to solve this?
An anonymous struct declaration is a declaration that declares neither a tag for the struct, nor an object or typedef name. Anonymous structs are not allowed in C++. The -features=extensions option allows the use of an anonymous struct declaration, but only as member of a union.
Anonymous unions/structures are also known as unnamed unions/structures as they don't have names. Since there is no names, direct objects(or variables) of them are not created and we use them in nested structure or unions. Definition is just like that of a normal union just without a name or tag.
Structure with private members in C++ Sometimes a question arose "Can a structure has private members?" The answer is "Yes! In C++, we can declare private members in the structure". So the important thing is that "we can declare a structure just like a class with private and public members".
An anonymous union is a union without a name. It cannot be followed by a declarator. An anonymous union is not a type; it defines an unnamed object. The member names of an anonymous union must be distinct from other names within the scope in which the union is declared.
If you're willing to modify your methods on the interface, you can do slightly better than void *
:
struct CHandle {
void *p;
CHandle(void *p): p(p) { }
};
struct CRequest {
void *p;
CRequest(void *p): p(p) { }
};
static CHandle make(Handle handle) { return CHandle(handle); }
static Handle get(CHandle handle) { return static_cast<Handle>(handle.p); }
static CRequest make(Request request) { return CRequest(request); }
static Request get(CRequest request) { return static_cast<Request>(request.p); }
Here, CHandle
and CRequest
have linkage and so can be used in your method signatures; the overloads of make
and get
have internal linkage and so can interface with the anonymous types. You can put this in a header, even the static
functions.
You'll have to modify your code so that when e.g. MyCls::myFct
calls into the library, you wrap parameters with get
and return values with make
.
You can introduce names by declaring new types, which simply contain these elements. Use those types for your parameters.
namespace MON {
struct t_handle {
Handle handle;
};
class MyCls {
public:
static void* myFct(t_handle handle);
...
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With