I think I recently ran into the same problem as the original poster, and have resolved it as below:
I am writing a wrapper around a third-party provided API defined as:
Foo.h:
typedef struct _foo
{
int i;
} Foo;
Foo* MakeFoo();
int UseFoo(Foo* foo);
My wrapper needs to have Foo as a member, but I don't want to expose Foo to all consumers of my wrapper.
UberFoo.h:
#pragma once
struct _foo; // forward declare the actual type _foo, not the typedef Foo
class UberFoo
{
public:
UberFoo();
int GetAnswer();
private:
_foo* f;
};
UberFoo.cpp:
#include "UberFoo.h"
#include "Foo.h"
UberFoo::UberFoo()
{
this->f = MakeFoo();
}
int UberFoo::GetAnswer()
{
return UseFoo(f);
}
Now, the consumers of my class can instantiate it without having access to the actual definition of _foo/Foo. This would also work if I needed to pass pointers to _foo as parameters or return them from functions as well as having a member _foo.
main.cpp:
#include <cstdio>
#include "UberFoo.h"
int main(int argc, char* argv[])
{
UberFoo u;
printf( "The Answer = %d\n", u.GetAnswer());
return 0;
}
The trick here was to forward declare the actual struct type, not the typedef'd name. Note that it is critical that the struct not be anonymous, as is common in older C code:
typedef struct // the actual struct type underlying the typedef is anonymous here
{
int i;
} ThisWontWork;
Hope this helps!