With debug symbols
Most of these answers seem to completely ignore debug symbols.
Using tools like NSA's Ghidra, it's very easy to "Export C headers", given that the DLL (or shared objects) was built with debug symbols, or if debug symbols are available via PDB (under Windows).
(Furthermore this even works with plain object files.
So if you lost your headers at some point during development, you can use that to recreate them).
Ghidra usually picks up the PDB next to the DLL, but it can be manually specified, via the "Load PDB Manually" function under File.
To export the headers, right click the imported DLL, in the "Data Type Manager" pane in Ghidra in the lower left corner and select "Export C Header".
You might want to move the types you're actually interested in to a new archive, before though, as debug symbols include definitions beyond just the interface.
Furthermore there exist utilities like pdbex, that allow to directly export headers.
With name mangling
With Ghidra or any other RE tool like IDA Pro, in general, it's fairly easy to analyze and recreate structures, compatible with the original library.
Given, that the name mangling of C++ exposes the function types, it's going to be like a game of Sudoku (or less spectacularly, a task of Gaussian elimination), to figure out the types.
For example, assuming we have a function, with prototype
Texture *CreateTexture(const BITMAP *pBitmap);
and another function for obtaining the size of the Texture:
size_t GetTextureWidth(Texture *pTexture);
then, finding out the structure of Texture is trivial, as it will contain code that looks like this
size_t GetTextureWidth(Texture *pTexture)
This will allow the reverse engineer to simply determine, at which offset the member was located and therefore recreate the headers.
Intercepting API calls
Recreating the headers for using a library isn't really that hard,
and wrapper libraries can be used to intercept and analyze function calls.
(For getting a decent idea of how to use the library or patching bugs).
Using LD_PRELOAD for example under Linux (similar ways exist for Windows). This will allow to preload the wrapper library so your symbols get resolved before the actual library. Then you can call the original symbols.
I've prepared such a patch once, to work around a bug present in a library.
It comes in very handy, when working with libraries that have memory management issue, for example because their reference counted resources are never freed internally. Or because they tried to fit the current working directory into a buffer, that they didn't allocate enough memory for.
Without name mangling
Even without name mangling, most API is easily reverse engineered, because the tools can derive the number and size of arguments as well as return type.
So even without name mangling, you would get something like:
undefined8 GetTextureWidth(astruct_1 *param_1)
which is still pretty obvious.
Without symbol names
Another important thing to mention is, that the names of the symbols can be omitted in Windows and replaced with ordinal numbers.
In this case, the ".lib" file contains the name and the ordinal number, which can be dumped using "dumpbin". Without the ".lib" file, the reverse engineer only knows, that a function is present.
undefined8 FUN_0000BEE0(astruct_1 *param_1)
Making it much harder, but still easy enough.
I would however suggest against ever doing that, as it only complicates the build process, doesn't really stop any determined reverse-engineer and only stops legit customers from potentially fixing some bugs themselves.
Manually analyzing the assembly is no longer necessary, with the tools currently freely available.
For your question, having LGPL headers, makes sense, as it allows people to implement their own library with their own license (like MIT) and continue using code they wrote for it in their own project, as well as the project that used the LGPL headers, assuming it's compatible with your LICENSE.
(It might or might not infect your library with LGPL, though. But that is a purely legal question, I'm not qualified to answer).
I don't see however, how this is in any way influenced by the ability to obtain the function prototypes and type structures, which is very easy to do.