VS 2005: __clrcall error exporting DLL functions which are not __clrcall? + /clr:pure/safe question

  • Thread starter Gustavo L. Fabro
  • Start date
G

Gustavo L. Fabro

Greetings!

Some classes that once compiled without problems on VS 2003 have now
problems on VS 2005 Beta 1. I'm talking about a __nogc class that is
exported with __declspec(dllexport).

The compiler message is this:

VCSelectLibraryForm.cpp
...\Forms\QiForm.h(48) : error C3395: 'TQiForm::GetDotNetMouseButton' :
__declspec(dllexport) cannot be applied to a function with the __clrcall
calling convention

This is odd because I'm not using "__clrcall" anywhere in my code (at least
not explicitly). Not in the function declaration, not in the class
declaration, anywhere!

I have 2 questions then:

1st) Any reason why this could be happening? Project options, parameter that
might make all calls on a given project __clrcall, etc?

2nd) Independently of the problem: I know an exported function from a DLL
can't be guaranteed to be called from a managed site. Thus, theoretically it
can't be exported. Is this the end of the story? I mean, if I compile code
with /clr:safe or /clr:pure in order to cut the unmanaged entry points from
functions and have a complete MSIL code, I won't be able to modularize it in
DLLs?

My compilation parameters are:

("Arquivos de programas" is the portuguese version of the "Program Files"
folder) ;)

/Od /Og /Ob2 /Oi /Ot /I "C:\Arquivos de programas\Microsoft Visual Studio
..NET 2003\Vc7\PlatformSDK\Include" /I "." /I ".." /I "..\..\Libbuilder" /I
"..\..\Persistence" /I "..\..\QiReportBuilder" /I
"..\..\Controls.NET\QiControls" /AI "..\VCRLibDll" /D "WIN32" /D "NDEBUG" /D
"_WINDOWS" /D "_USRDLL" /D "QIVFORMS_EXPORTS" /D "VISUAL_C" /D "NULL=0" /D
"_USE_MATH_DEFINES" /D "__TRACE" /D "_WINDLL" /D "_MBCS" /FD /EHa /MD /GS
/GR /Fo"..\VCRObj/" /Fd"..\VCRObj/vc80.pdb" /W3 /nologo /c /Wp64 /Zi
/clr:blush:ldSyntax /TP /wd4290 /wd4251 /wd4275 /wd4311 /wd4800 /FU
"QiVControls.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\Microsoft.VisualC.Dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\mscorlib.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.Data.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.Design.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.Drawing.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.Windows.Forms.dll" /FU
"c:\WINXP\Microsoft.NET\Framework\v2.0.40607\System.XML.dll"

Thanks,
Fabro
 
S

Sri Vasudevan [MSFT]

1) __clrcall is implicit for managed types (__nogc and __gc) classes.
__declspec(dllexport) does not apply to managed types. Hence, it is now
disallowed.
2) I am not sure I understand your question here. As long as your type is
not a managed type and you don't explicitly specify __clrcall, you should be
able to export it

Thx,
 
G

Gustavo L. Fabro

Hi there!
1) __clrcall is implicit for managed types (__nogc and __gc) classes.
__declspec(dllexport) does not apply to managed types. Hence, it is now
disallowed.

Hmmm Let me get this straight:

You said "managed types (__nogc and __gc) classes". Don't you mean managed
code?

As far as I knew (please clear up my mess, if that's the case), a __nogc
keyword "Explicitly declares an unmanaged type."
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/vclrf__nogc.asp)

Still from the help,
"Objects of this type are similar to standard C++ objects in that they are
allocated from the standard C++ heap and are not subject to the restrictions
of a managed object"

This is one of the restrictions (not being able to export). In that case
(with the __nogc keyword), it wouldn't have the restriction. Right?
2) I am not sure I understand your question here. As long as your type is
not a managed type and you don't explicitly specify __clrcall, you should
be able to export it.

I should be able to export it even if It's an unmanaged type running on a
managed code (because it was compiled with /clr)?

My question was for managed types. It's a design question:

Suppose I want to write a 100% C++/CLI code, using only .NET, MSIL and not a
line of native code.

In this particular scenario, by the information I'm having, I cannot use
__declspec(dllexport) to export a function from a DLL. Does this means DLLs
do not exist on .NET Framework World? Because what would be the point of
having a DLL if I couldn't acess any of its functions? :)

Thanks for the attention,

Fabro
 
S

Sri Vasudevan [MSFT]

1) Sorry. I meant gc classes (value and ref types (in new syntax)) have
implicit clrcall calling convention and hence cannot use dllexport. I don't
see this behavior on __nogc classes (unmanaged types) on Beta 1. Do you
have a small snippet of code which throws this error?

2) Managed code in assemblies can be exposed by simply declaring them
public. The user of the assembly can add a reference to the dll by using
either #using syntax, by using the /FU compiler switch to force a reference
etc.,

Thx,
 
G

Gustavo L. Fabro

Hi there! Thanks for the replies!

Answering backwards...

2) Managed code in assemblies can be exposed by simply declaring them
public. The user of the assembly can add a reference to the dll by using
either #using syntax, by using the /FU compiler switch to force a reference
etc.,

Great! I searched for the keywords and now things are much clearer.

1) Sorry. I meant gc classes (value and ref types (in new syntax)) have
implicit clrcall calling convention and hence cannot use dllexport. I don't
see this behavior on __nogc classes (unmanaged types) on Beta 1. Do you
have a small snippet of code which throws this error?

In fact I do! I searched my class and found the offending code!
A code like this will compile on 2003 without problems but will fail to
compile on 2005 with C3395:

Instructions:

- add a reference to System.Windows.Forms.dll (.NET 1.1.4322 on VS 2003 and
2.0.40607 on VS 2005 B1)
- compile with /clr:blush:ldSyntax

class __declspec(dllexport) TestClass
{
public:

TestClass();

int GetDotNetMouseButton(
System::Windows::Forms::MouseButtons button
);

};

Could this be happening because I'm using a .NET type,
System::Windows::Forms::MouseButtons, on my theoretically __nogc class? As
my unmanaged class is trying to access a managed type, the compiler makes it
managed?

If this is the case (I think it is), how did this work back in VS 2003? ;-)

Thanx
 
K

Kapil Khosla [MSFTt]

--
This posting is provided "AS IS" with no warranties, and confers no
rights."Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm"

Gustavo L. Fabro said:
Hi there! Thanks for the replies!

Answering backwards...

2) Managed code in assemblies can be exposed by simply declaring them
public. The user of the assembly can add a reference to the dll by using
either #using syntax, by using the /FU compiler switch to force a
reference
etc.,

Great! I searched for the keywords and now things are much clearer.

1) Sorry. I meant gc classes (value and ref types (in new syntax)) have
implicit clrcall calling convention and hence cannot use dllexport. I
don't
see this behavior on __nogc classes (unmanaged types) on Beta 1. Do you
have a small snippet of code which throws this error?

In fact I do! I searched my class and found the offending code!
A code like this will compile on 2003 without problems but will fail to
compile on 2005 with C3395:

Instructions:

- add a reference to System.Windows.Forms.dll (.NET 1.1.4322 on VS 2003
and 2.0.40607 on VS 2005 B1)
- compile with /clr:blush:ldSyntax

class __declspec(dllexport) TestClass
{
public:

TestClass();

int GetDotNetMouseButton(
System::Windows::Forms::MouseButtons button
);

};

Could this be happening because I'm using a .NET type,
System::Windows::Forms::MouseButtons, on my theoretically __nogc class? As
my unmanaged class is trying to access a managed type, the compiler makes
it managed?

If this is the case (I think it is), how did this work back in VS 2003?
;-)

Thanx







Hi Gustavo,
Thanks for the repro. First to answer your question, we currently dont allow
a native class member function which takes an argument of a manged type if
you try to export the class or member functions. It would work if you dont
export the class. Let me try to explain why.

When you have dllexport on your class or members, you create an entry in the
import virtual table. When a call is made to that function, it goes through
the IVT. In the case of a native function, we create a thunk to convert the
native call to a MSIL. For example, if you native function took char* as an
argument, we could convert it to String which is the equivalent managed
transformation.

In your example however, the function was "managed" and thus it had a
__clrcall calling convention. We could not do the thunking in this case and
thus the call failed.
Hope it helps. I know that thunking is not very well documented yet but I
will try to find some docs and post them.

Thanks,
Kapil
 
G

Gustavo L. Fabro

Hi there,
Hi Gustavo,
Thanks for the repro. First to answer your question, we currently dont
allow a native class member function which takes an argument of a manged
type if you try to export the class or member functions. It would work if
you dont export the class. Let me try to explain why.

When you have dllexport on your class or members, you create an entry in
the import virtual table. When a call is made to that function, it goes
through the IVT. In the case of a native function, we create a thunk to
convert the native call to a MSIL. For example, if you native function
took char* as an argument, we could convert it to String which is the
equivalent managed transformation.

In your example however, the function was "managed" and thus it had a
__clrcall calling convention. We could not do the thunking in this case
and thus the call failed.
Hope it helps. I know that thunking is not very well documented yet but I
will try to find some docs and post them.

It took me a while to reply because we were at carnival here in Brazil...
;-)

Thanx for the explanation and the URL to the docs. I'll definitely read
them.

Best regards,
Fabro
 
Top