C3395: __declspec(dllexport) and __clrcall incompatible

  • Thread starter Jochen Kalmbach [MVP]
  • Start date
J

Jochen Kalmbach [MVP]

Hi bonk!
Hello, I created a MFC extension dll (using VS 2005 Beta 2) that is
supposed to export a class that uses .NET internally (See header below)
und later shall be used by a plain MFC Project (without the /CLR).

As soon as I try to specify __declspec(dllexport) (AFX_EXT_CLASS) I get
the following compiler error:

Error 2 error C3395: 'CWPFControlProxy::OnWPFButtonClick' :
__declspec(dllexport) cannot be applied to a function with the __clrcall
calling convention g:\robert_d\visual studio
2005\projects\wpfcontrols\wpfcontrols\WPFControlProxy.h 28

Could you explain what this error means and what I can do against it? I
don't see a __clrcall definition anywhere in my project ...

If you compile with /clr, then all methods/functions are compiled into
MSIL, therefor they will always use __clrcall as calling convention.

If you want to have __stdcall or __cdecl then you need to compile into
native code.

So please add the

#pragma unmanaged

to the region of code, you want to export.

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
B

bonk

Hello, I created a MFC extension dll (using VS 2005 Beta 2) that is
supposed to export a class that uses .NET internally (See header below)
und later shall be used by a plain MFC Project (without the /CLR).

As soon as I try to specify __declspec(dllexport) (AFX_EXT_CLASS) I get
the following compiler error:

Error 2 error C3395: 'CWPFControlProxy::OnWPFButtonClick' :
__declspec(dllexport) cannot be applied to a function with the __clrcall
calling convention g:\robert_d\visual studio
2005\projects\wpfcontrols\wpfcontrols\WPFControlProxy.h 28

Could you explain what this error means and what I can do against it? I
don't see a __clrcall definition anywhere in my project ...

---- WPFControlProxy.h ------------------

#pragma once

// CWPFControlProxy
#include <msclr\event.h>
#include <msclr\auto_gcroot.h>
using namespace System;
using namespace System::Windows;
using namespace System::Windows::Controls;
using namespace System::Windows::Media;

class AFX_EXT_CLASS CWPFControlProxy : public CStatic
{
DECLARE_DYNAMIC(CWPFControlProxy)
public:
CWPFControlProxy();
virtual ~CWPFControlProxy();
CRect m_borders;
private:
HWND m_WPFHwnd;
CString m_WPFText;
Visual^ CreateRootWPFVisual();
msclr::auto_gcroot<TextBox^> m_wpfTextBox;
void OnWPFButtonClick (Object^ sender, RoutedEventArgs^ eargs);
public:
BEGIN_DELEGATE_MAP(CWPFControlProxy)
EVENT_DELEGATE_ENTRY(OnWPFButtonClick,Object^, RoutedEventArgs^)
END_DELEGATE_MAP()
void SetText (LPCTSTR text);
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnSetText( WPARAM, LPARAM );
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};
 
B

bonk

Jochen said:
So please add the

#pragma unmanaged

to the region of code, you want to export.
Does that mean if I want to export a class it is impossible for that
class to have methods that return managed types or take managed types as
parameters ? Even if the method is private? What about (private) member
types, can they be managed ?
 
J

Jochen Kalmbach [MVP]

Hi bonk!
Does that mean if I want to export a class it is impossible for that
class to have methods that return managed types or take managed types as
parameters ? Even if the method is private? What about (private) member
types, can they be managed ?

If your class will be used by unamanged apps, then you cannot export
managed methods (even if the method is private, because the whole
v-table will be different)!

If you want to export managed classes, then you simply need to make it
public (no need of exporting it).

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
B

bonk

Jochen said:
Hi bonk!



If your class will be used by unamanged apps, then you cannot export
managed methods (even if the method is private, because the whole
v-table will be different)!

If you want to export managed classes, then you simply need to make it
public (no need of exporting it).


Is it ok to have managed types as members of a class I wanto dllexport?
And are there any common pitfalls I should watch out for? I am trying to
create a dll that internally works with managed types but exports on
unmanaged "Interfaces". So that a unmanaged (one without the /clr) MFC
project can use that dll.
 
J

Jochen Kalmbach [MVP]

Hi bonk!
Is it ok to have managed types as members of a class I wanto dllexport?

You can´t have them directly; only via gcroot-templates... (but then it
is possible).
And are there any common pitfalls I should watch out for? I am trying to
create a dll that internally works with managed types but exports on
unmanaged "Interfaces". So that a unmanaged (one without the /clr) MFC
project can use that dll.

I don´t know if this will work out of the box... (AFAIK: No, but I have
never tested it...).

You need some kind of CLR_Hosting in the main app...
See: CLR Hosting
http://www.gotdotnet.com/team/clr/what_is_clr_hosting.aspx


--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
M

Marcus Heege

Hi Jochen,
Jochen Kalmbach said:
Hi bonk!

If you compile with /clr, then all methods/functions are compiled into
MSIL, therefor they will always use __clrcall as calling convention.

If you want to have __stdcall or __cdecl then you need to compile into
native code.

So please add the

#pragma unmanaged

to the region of code, you want to export.

Sorry to correct you here, but your statement is wrong. Managed functions
can indeed have native calling conventions. In these cases special metadata
is generated that the CLR can use to generate unmanaged -> managed thunks.
The calling convention __clrcall exists only to avoid the generation of this
metadata and the managed -> unmanaged thunks in cases where they are not
necessary.

See [1] for the details.

Marcus Heege

[1]
http://www.heege.net/blog/PermaLink,guid,48daf2ff-41c8-4312-9d80-bdfa8c55058d.aspx
 
M

Marcus Heege

Hi Bonk,

bonk said:
Hello, I created a MFC extension dll (using VS 2005 Beta 2) that is
supposed to export a class that uses .NET internally (See header below)
und later shall be used by a plain MFC Project (without the /CLR).

As soon as I try to specify __declspec(dllexport) (AFX_EXT_CLASS) I get
the following compiler error:

Error 2 error C3395: 'CWPFControlProxy::OnWPFButtonClick' :
__declspec(dllexport) cannot be applied to a function with the __clrcall
calling convention g:\robert_d\visual studio
2005\projects\wpfcontrols\wpfcontrols\WPFControlProxy.h 28

Could you explain what this error means and what I can do against it? I
don't see a __clrcall definition anywhere in my project ...

---- WPFControlProxy.h ------------------

#pragma once

// CWPFControlProxy
#include <msclr\event.h>
#include <msclr\auto_gcroot.h>
using namespace System;
using namespace System::Windows;
using namespace System::Windows::Controls;
using namespace System::Windows::Media;

class AFX_EXT_CLASS CWPFControlProxy : public CStatic
{
DECLARE_DYNAMIC(CWPFControlProxy)
public:
CWPFControlProxy();
virtual ~CWPFControlProxy();
CRect m_borders;
private:
HWND m_WPFHwnd;
CString m_WPFText;
Visual^ CreateRootWPFVisual();
msclr::auto_gcroot<TextBox^> m_wpfTextBox;
void OnWPFButtonClick (Object^ sender, RoutedEventArgs^ eargs);
public:
BEGIN_DELEGATE_MAP(CWPFControlProxy)
EVENT_DELEGATE_ENTRY(OnWPFButtonClick,Object^, RoutedEventArgs^)
END_DELEGATE_MAP()
void SetText (LPCTSTR text);
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnSetText( WPARAM, LPARAM );
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};

Here is what went wrong with your code:

1) You export a native class via __declspec(dllexport)
2) This exports the functions of the native class
3) Although managed functions, functions have a native calling convention -
these functions can easily be exported
4) Some managed functions have the calling convention __clrcall (not because
you explicitly wrote that, but because functions with managed types in their
signature can only have this calling convention.
5) __clrcall calling conventions can not be exported by DLLs - trying to
export them causes the problems you see here.

__clrcall tells the compiler that it should not create unmanaged->managed
thunks, but to export managed functions, unmanaged->managed thunks are
needed.
 
J

Jochen Kalmbach [MVP]

Hi Marcus!
Sorry to correct you here, but your statement is wrong. Managed functions
can indeed have native calling conventions. In these cases special metadata
is generated that the CLR can use to generate unmanaged -> managed thunks.
The calling convention __clrcall exists only to avoid the generation of this
metadata and the managed -> unmanaged thunks in cases where they are not
necessary.

Yes, you are right... sorry for the confusion...

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 

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