Problem converting to mixed mode c++

P

PLS

I have a program that uses the OwlNext library. I am trying to get this
to compile with the /clr switch on. Needless to say, the program
compiles and works fine without this switch.

I end up with 12 errors, which are repetitions of these two:

1>vmonin.obj : error LNK2028: unresolved token (0A00056C) "protected:
virtual wchar_t const * __thiscall OWL::TEdit::GetClassName(void)" (?
GetClassName@TEdit@OWL@@$$FMAEPB_WXZ) referenced in function
"[thunk]:protected: virtual wchar_t const * __thiscall
OWL::TEdit::GetClassName`vtordisp{4294967292,0}' (void)" (?
GetClassName@TEdit@OWL@@$$F$2PPPPPPPM@A@AEPB_WXZ)

1>vmonwndw.obj : error LNK2028: unresolved token (0A0005C8) "public:
long __thiscall OWL::TWindow::SendMessage(unsigned int,unsigned
int,long)const " (?SendMessage@TWindow@OWL@@$$FQBEJIIJ@Z) referenced in
function "protected: virtual void __thiscall vmonWindow::SetupWindow
(void)" (?SetupWindow@vmonWindow@@$$FMAEXXZ)

Apparently the linker found a great many other functions, but not these
two. Both functions are class members. Here is the source for the two
functions:

Header:
LPCTSTR GetClassName();
Implementation:
LPCTSTR
TDialog::GetClassName()
{
return (LPCTSTR)WC_DIALOG;
}

Header:
TResult SendMessage(uint msg, TParam1 p1 = 0, TParam2 p2 = 0) const;
Implementation:
TResult
TWindow::SendMessage(uint msg, TParam1 param1, TParam2 param2) const
{
PRECONDITION(GetHandle());

TResult result = ::SendMessage(GetHandle(), msg, param1, param2);
return result;
}


I don't get it. Why would these functions have a problem and the many
others apparenty not?

Thanks,
++PLS
 
O

Ognian Chernokozhev

Hello,

The problem probably is caused by this code in
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\WinUser.h

#ifdef UNICODE
#define GetClassName GetClassNameW
#else
#define GetClassName GetClassNameA
#endif // !UNICODE

and after that

#if defined(_M_CEE) // this is defined when /clr flag is used

#undef GetClassName
__inline
int
GetClassName(
HWND hWnd,
LPTSTR lpClassName,
int nMaxCount
)
{
#ifdef UNICODE
return GetClassNameW(
#else
return GetClassNameA(
#endif
hWnd,
lpClassName,
nMaxCount
);
}
#endif /* _M_CEE */


The result is that OWLNext libraries are compiled without the /clr flag and because of the preprocessor definition, the functions are silently renamed to GetClassNameA or GetClassNameW - this can be seen by exploring owl-630-v9-t.dll with a tool like DependencyWalker, which shows the exported symbols.

When compiling normally with VC++, this is no problem, as the same preprocessor definition is in effect.


A quick and dirty solution is to restore the preprocessor definition, after winuser.h is included, but before any OWLNext classes are defined.
This can be done by adding the following code in include/owl/defs.h, after line 116 with the comment
// Additional windows.h related defines & undefs for Owl compatibility

New code:

#if defined(_M_CEE) // this is defined when /clr flag is used

#if !defined(GetClassName)
#ifdef UNICODE
#define GetClassName GetClassNameW
#else
#define GetClassName GetClassNameA
#endif // !UNICODE
#endif

#if !defined(SendMessage)
#ifdef UNICODE
#define SendMessage SendMessageW
#else
#define SendMessage SendMessageA
#endif // !UNICODE
#endif

#if !defined(GetTextMetrics)
#ifdef UNICODE
#define GetTextMetrics GetTextMetricsW
#else
#define GetTextMetrics GetTextMetricsA
#endif // !UNICODE
#endif

#if !defined(DrawText)
#ifdef UNICODE
#define DrawText DrawTextW
#else
#define DrawText DrawTextA
#endif // !UNICODE
#endif

#endif

If there are additional unresolved functions, add similar defines for them.


After making this change, there is no need to recompile OWLNext, just your application - I built successfully
OWLMaker with /clr option.

Jogy

P.S. I have planed for next year working OWLNext compatibility with VC++ /clr but haven't done yet, so I can offer no guarantee that there are no other hidden problems.









PLS wrote:

Problem converting to mixed mode c++
06-Dec-07

I have a program that uses the OwlNext library. I am trying to get this
to compile with the /clr switch on. Needless to say, the program
compiles and works fine without this switch.

I end up with 12 errors, which are repetitions of these two:

1>vmonin.obj : error LNK2028: unresolved token (0A00056C) "protected:
virtual wchar_t const * __thiscall OWL::TEdit::GetClassName(void)" (?
GetClassName@TEdit@OWL@@$$FMAEPB_WXZ) referenced in function
"[thunk]:protected: virtual wchar_t const * __thiscall
OWL::TEdit::GetClassName`vtordisp{4294967292,0}' (void)" (?
GetClassName@TEdit@OWL@@$$F$2PPPPPPPM@A@AEPB_WXZ)

1>vmonwndw.obj : error LNK2028: unresolved token (0A0005C8) "public:
long __thiscall OWL::TWindow::SendMessage(unsigned int,unsigned
int,long)const " (?SendMessage@TWindow@OWL@@$$FQBEJIIJ@Z) referenced in
function "protected: virtual void __thiscall vmonWindow::SetupWindow
(void)" (?SetupWindow@vmonWindow@@$$FMAEXXZ)

Apparently the linker found a great many other functions, but not these
two. Both functions are class members. Here is the source for the two
functions:

Header:
LPCTSTR GetClassName();
Implementation:
LPCTSTR
TDialog::GetClassName()
{
return (LPCTSTR)WC_DIALOG;
}

Header:
TResult SendMessage(uint msg, TParam1 p1 = 0, TParam2 p2 = 0) const;
Implementation:
TResult
TWindow::SendMessage(uint msg, TParam1 param1, TParam2 param2) const
{
PRECONDITION(GetHandle());

TResult result = ::SendMessage(GetHandle(), msg, param1, param2);
return result;
}


I don't get it. Why would these functions have a problem and the many
others apparenty not?

Thanks,
++PLS

Previous Posts In This Thread:

Problem converting to mixed mode c++
I have a program that uses the OwlNext library. I am trying to get this
to compile with the /clr switch on. Needless to say, the program
compiles and works fine without this switch.

I end up with 12 errors, which are repetitions of these two:

1>vmonin.obj : error LNK2028: unresolved token (0A00056C) "protected:
virtual wchar_t const * __thiscall OWL::TEdit::GetClassName(void)" (?
GetClassName@TEdit@OWL@@$$FMAEPB_WXZ) referenced in function
"[thunk]:protected: virtual wchar_t const * __thiscall
OWL::TEdit::GetClassName`vtordisp{4294967292,0}' (void)" (?
GetClassName@TEdit@OWL@@$$F$2PPPPPPPM@A@AEPB_WXZ)

1>vmonwndw.obj : error LNK2028: unresolved token (0A0005C8) "public:
long __thiscall OWL::TWindow::SendMessage(unsigned int,unsigned
int,long)const " (?SendMessage@TWindow@OWL@@$$FQBEJIIJ@Z) referenced in
function "protected: virtual void __thiscall vmonWindow::SetupWindow
(void)" (?SetupWindow@vmonWindow@@$$FMAEXXZ)

Apparently the linker found a great many other functions, but not these
two. Both functions are class members. Here is the source for the two
functions:

Header:
LPCTSTR GetClassName();
Implementation:
LPCTSTR
TDialog::GetClassName()
{
return (LPCTSTR)WC_DIALOG;
}

Header:
TResult SendMessage(uint msg, TParam1 p1 = 0, TParam2 p2 = 0) const;
Implementation:
TResult
TWindow::SendMessage(uint msg, TParam1 param1, TParam2 param2) const
{
PRECONDITION(GetHandle());

TResult result = ::SendMessage(GetHandle(), msg, param1, param2);
return result;
}


I don't get it. Why would these functions have a problem and the many
others apparenty not?

Thanks,
++PLS


Submitted via EggHeadCafe - Software Developer Portal of Choice
Easy Cross-Browser Collapsible Divs Redux
http://www.eggheadcafe.com/tutorial...63-6e9095a9597a/easy-crossbrowser-collap.aspx
 

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