warning C4251 using gcroot<> accross multiple native dlls

G

Guest

Hello,

I have a class hierarchy distributed over 3 native C++ dlls. The base class
has a .NET Windows.Form for status output via a gcroot<>.
The gcroot is declared private - the sub classes only have access via a
protected "print"-method.
I need the different dlls as the sub classes implement the base class's pure
virtual methods using different technologies.
To use the native classes from outside their dlls I use the
__declspec(dllexport) marco. This all works without any runtime error.

Still when the sub classes' dlls are compiled I get the following warning
(for each sub class):

warning C4251: 'UnmanagedComponent::m_pFormDebugOutput' : struct 'gcroot<T>'
needs to have dll-interface to be used by clients of class
'UnmanagedComponent'

where "UnmanagedComponent" is my base class and "m_pFormDebugOutput" is the
"private"-declared gcroot<> of type Windows.Forms.Form.

What does this warning mean in this respect? Is there a solution to get rid
of it (apart from switching it off)?

Thanks a lot in advance. Regards,

Fabian
 
C

Cholo Lennon

The warning doesn't matter unless some inline member function of
UnmanagedComponent (or its derived classes) uses pFormDebugOutput in some way
other than a simple pointer reference. If it is the case (access member
functions through the pointer) you have to export gcroot<>

IMO the best solution is to use the pimpl idiom to get rid of private members
from the interface definition.

Regards
 
G

Guest

Hi Cholo,
If it is the case (access member functions through the pointer) you have to export gcroot<>

How would I do this in this case?

__declspec(dllexport) gcroot<FormDebugOutput^>;

in the header file makes the compiler produce the following message:

IMO the best solution is to use the pimpl idiom to get rid of private members
from the interface definition.

How much performance would this additional redirection cost? My design
already is performance consuming: Calling into the gcroot<> should take at
least one context switch.

Thanks a lot for your help,

Fabian
 
C

Cholo Lennon

How would I do this in this case?
__declspec(dllexport) gcroot<FormDebugOutput^>;

in the header file makes the compiler produce the following message:

warning C4091: '__declspec(dllexport)' : ignored on left of 'gcroot<T>' when
no variable is declared

To view an example of how to export a template take a look to:
http://support.microsoft.com/?scid=kb;en-us;168958&x=12&y=10

The problem with dllexport is that it's incompatible with __clrcall convention
(used by clr objects) :-( so you cannot export a template with clr types (I
didn't know it until today). If you don't have inline functions that use use
How much performance would this additional redirection cost? My design
already is performance consuming: Calling into the gcroot<> should take at
least one context switch.

It's depends of how you implement the pimpl idiom. If you use a raw pointer or
boost::scoped_ptr, the penalty is minimum (almost nothing; the compiler adds
only one instruction). If you use boost::shared_ptr the penalty increase. Just
take a look the generated asm code using a raw pointer:

class Foo {
...
void pimplCall();
void directCall();

ToCall m_toCall;

struct Impl;
Impl* m_pImpl;
...
};

struct Foo::Impl {
ToCall m_toCall;
};

pImpl call: m_pImpl->m_toCall.Test();
00401057 mov eax,dword ptr [this]
0040105A mov ecx,dword ptr [eax+4]
0040105D call ToCall::Test (401000h)

Direct call: m_toCall.Test();
00401077 mov ecx,dword ptr [this]
0040107A call ToCall::Test (401000h)


Regards

PS: [boost] Remember that If your class is non copyable you can use
boost::scoped_ptr. If your class is copyable you have to use boost::shared_ptr
 
F

Fabian

Hi Cholo,
The problem with dllexport is that it's incompatible with __clrcall convention
(used by clr objects) :-( so you cannot export a template with clr types (I
didn't know it until today).

If you create a pure win32 dll with the VS wizard it has __stdcall
convention. Compiled with /clr you get a dll which can both use clr objects
via a gcroot<> and export native classes that use a gcroot.
But then we're back to the beginning: The class export works, but the
compiler complains about the non-exported gcroot member.

thanks a lot for your help,

Fabian
 
B

Ben Voigt [C++ MVP]

Fabian said:
Hi Cholo,


How would I do this in this case?

__declspec(dllexport) gcroot<FormDebugOutput^>;

in the header file makes the compiler produce the following message:

warning C4091: '__declspec(dllexport)' : ignored on left of 'gcroot<T>'
when
no variable is declared


How much performance would this additional redirection cost? My design
already is performance consuming: Calling into the gcroot<> should take at
least one context switch.

gcroot should not cause a context switch unless combined with Remoting.

pimpl's performance cost is a tiny fraction of a context switch, maybe
1/1000.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top