PDA

View Full Version : extern "C" issue



Anti-Distinctly
09-27-2007, 02:21 PM
Having a bit of trouble getting my code to compile with the extern "C" command.

Here is the code:



#include <lwserver.h>
#include <lwdisplce.h>
#include <lwmeshes.h>

typedef struct st_MyData{
LWTime time; //Current time
} MyData;

XCALL_( int )
Activate( long version, GlobalFunc *global, LWDisplacementHandler *local, void *serverData)
{
return AFUNC_OK;
}

extern "C"{
ServerRecord ServerDesc[] = {
{ (const char*)LWDISPLACEMENT_HCLASS, (const char*)"TAStab", (ActivateFunc*)Activate },
{ NULL }
};
}


I'm not using the static lib, I've just added servmain.c, shutdown.c and startup.c to teh project.
My compiler settings are as follows, (I'm not sure if some if them are irrelevant or whatever as I'm still finding my feet with the whole plugin writing thing, but they work for C)
These are the settings that are changed from their defaults of a dll project not using precompiled headers:

General
Configuration type -> dll
Output directory -> whatever
Debugging
Command -> Layout/Modeler.exe
Command Arguments -> –0 –d“debug output directory” –c“content directory” –p“plugin directory”
Working Directory -> Same as ‘start in’ on shortcut
C/C++
Additional include directories -> path to SDK ‘include’ directory
Preprocessor definitions, Add-> _X86_; _MSWIN
Compile As -> C++ Code
Linker
Output file -> change extension to .p
Module Definition File -> ‘serv.def’, note: this file exists to exist in the solution directory
serv.def simply reads:

LIBRARY
EXPORTS
_mod_descrip


The error I'm getting is:


Error 1 error LNK2001: unresolved external symbol "struct st_ServerRecord * ServerDesc" ([email protected]@[email protected]@A) servmain.obj
Error 2 fatal error LNK1120: 1 unresolved externals C:\Program Files\NewTek\LightWave 3D 9.3\Plugins\My Plugins\TAStab\Debug\TAStab.p 1


Any ideas?

Anti-Distinctly
09-27-2007, 02:54 PM
OK, as I switched the Compile As option to C++ Code of course the shutdown, startup and servmain files aren't going to work.
I just threw an extern "C" around the code in those files and it seems to compile now. Is this the correct thing to do?

Lightwolf
09-27-2007, 04:24 PM
You don't really need the extern "C" there. Actually, the only place you need it is for the _mod_descrip, since that is the only hook actually exported from the DLL.
That is, if you compile the rest of the code as C++.

Basically, extern "C" defines the type of linkage for the function/struct, and the linkage is only relevant if it is:
* static, i.e. object files or static libraries
* dynamic, such as dynamic libraries, in this case a DLL.

Cheers,
Mike

Anti-Distinctly
09-27-2007, 04:54 PM
Hi Mike,
I threw the extern "C" into the beginning of the serv.def (assuming that's what you meant) and it seemed to compile ok. Unfortunately, hooks and exporting symbols doesn't mean much to me I'm afraid :|
I'm trying to get the TrueAxis physics engine services (or whatever you want to call them) compiling in a plugin now and I'm getting a similar problem. Again its an unresolved external symbol problem. I really wish I knew what that actually meant.
I've set the path to the TrueAxis physics & common header files in the project's properties.
My code is now as follows



#include <lwserver.h>
#include <lwdisplce.h>
#include <lwmeshes.h>

#include <Physics.h>
#include <StaticObject.h>
#include <CollisionObjectComplex.h>

typedef struct st_MyData{
LWTime time; //Current time
} MyData;

XCALL_( int )
Activate( long version, GlobalFunc *global, LWDisplacementHandler *local, void *serverData)
{
TA::Physics& physics = TA::Physics::GetInstance();

return AFUNC_OK;
}


ServerRecord ServerDesc[] = {
{ (const char*)LWDISPLACEMENT_HCLASS, (const char*)"TAStab", (ActivateFunc*)Activate },
{ NULL }
};


And I'm getting this error


Error 2 error LNK2001: unresolved external symbol "private: static class TA::Physics * TA::Physics::lOllOlOOOOll" ([email protected]@[email protected]@[email protected]) TAStab.obj


I'm sure there's something fundamental that I've not grasped yet as this error in particular comes up a lot. Any help you could shed on this would be much appriciated.

Lightwolf
09-27-2007, 05:09 PM
Hi Mike,
I threw the extern "C" into the beginning of the serv.def (assuming that's what you meant) and it seemed to compile ok.
No, I meant the _mod_export in servmain.c.

Your plugin is a .cpp file? Compiled as C++?

I'd point you to an article on how compilers and linkers work, but googling "name mangling" (or name decoration) and extern "C".
http://en.wikipedia.org/wiki/Name_mangling
And since C and C++ use a different way of calling functions (and use a different name decoration) - extern "C" tells the C++(-compiled) code to stay compatible (within limits).

Cheers,
Mike

Anti-Distinctly
09-28-2007, 02:08 AM
Thanks Mike. You're a great help as always. I'll give that article a read...

Anti-Distinctly
10-01-2007, 04:00 AM
Mike,
I'm still trying to get my head around name mangling, while also trying to write a simple displacement plugin with no joy. I'm still compiling as C++ by using


extern "C"
ModuleDescriptor _mod_descrip =
#endif
{
MOD_SYSSYNC,
MOD_SYSVER,
MOD_MACHINE,
Startup,
Shutdown,
ServerDesc
};

I'm getting errors relating to the fact that the signatures for the callbacks don't match, thus;



Error 13 error C2440: '=' : cannot convert from 'const char *(__cdecl *)(InertiaData *)' to 'const char *(__cdecl *)(LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 537
Error 14 error C2440: '=' : cannot convert from 'const LWItemID *(__cdecl *)(InertiaData *)' to 'const LWItemID *(__cdecl *)(LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 539
Error 20 error C2440: '=' : cannot convert from 'int (__cdecl *)(InertiaData *)' to 'unsigned int (__cdecl *)(LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 547
Error 10 error C2440: '=' : cannot convert from 'LWError (__cdecl *)(InertiaData *,const LWLoadState *)' to 'LWError (__cdecl *)(LWInstance,const LWLoadState *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 534
Error 11 error C2440: '=' : cannot convert from 'LWError (__cdecl *)(InertiaData *,const LWSaveState *)' to 'LWError (__cdecl *)(LWInstance,const LWSaveState *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 535
Error 12 error C2440: '=' : cannot convert from 'LWError (__cdecl *)(InertiaData *,InertiaData *)' to 'LWError (__cdecl *)(LWInstance,LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 536
Error 16 error C2440: '=' : cannot convert from 'LWError (__cdecl *)(InertiaData *,int)' to 'LWError (__cdecl *)(LWInstance,int)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 542
Error 18 error C2440: '=' : cannot convert from 'LWError (__cdecl *)(InertiaData *,LWFrame,LWTime)' to 'LWError (__cdecl *)(LWInstance,LWFrame,LWTime)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 544
Error 9 error C2440: '=' : cannot convert from 'void (__cdecl *)(InertiaData *)' to 'void (__cdecl *)(LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 533
Error 17 error C2440: '=' : cannot convert from 'void (__cdecl *)(InertiaData *)' to 'void (__cdecl *)(LWInstance)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 543
Error 15 error C2440: '=' : cannot convert from 'void (__cdecl *)(InertiaData *,const LWItemID *)' to 'void (__cdecl *)(LWInstance,const LWItemID *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 540
Error 19 error C2440: '=' : cannot convert from 'void (__cdecl *)(InertiaData *,LWDisplacementAccess *)' to 'void (__cdecl *)(LWInstance,LWDisplacementAccess *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 546
Error 1 error C2440: '=' : cannot convert from 'void *' to 'InertiaData *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 189
Error 6 error C2440: '=' : cannot convert from 'void *' to 'LWChannelInfo *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 525
Error 5 error C2440: '=' : cannot convert from 'void *' to 'LWEnvelopeFuncs *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 524
Error 24 error C2440: '=' : cannot convert from 'void *' to 'LWInstUpdate (__cdecl *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 749
Error 7 error C2440: '=' : cannot convert from 'void *' to 'LWItemInfo *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 526
Error 4 error C2440: '=' : cannot convert from 'void *' to 'LWObjectFuncs *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 523
Error 8 error C2440: '=' : cannot convert from 'void *' to 'LWVParmFuncs *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 527
Error 21 error C2440: '=' : cannot convert from 'void *' to 'LWXPanelFuncs *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 719
Error 26 error C2440: 'initializing' : cannot convert from 'int (__cdecl *)(int,GlobalFunc (__cdecl *),LWDisplacementHandler *,void *)' to 'ActivateFunc (__cdecl *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 770
Error 27 error C2440: 'initializing' : cannot convert from 'int (__cdecl *)(int,GlobalFunc (__cdecl *),LWInterface *,void *)' to 'ActivateFunc (__cdecl *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 771
Error 25 error C2664: 'get_xpanel' : cannot convert parameter 2 from 'LWInstance' to 'InertiaData *' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 753
Error 23 error C2664: 'void (LWXPanelID,LWXPanelDataDesc *,LWXPanelGetFunc (__cdecl *),LWXPanelSetFunc (__cdecl *))' : cannot convert parameter 3 from 'LWXPanelDataDesc [5]' to 'LWXPanelGetFunc (__cdecl *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 724
Error 22 error C2664: 'void (LWXPanelID,LWXPanelDataDesc *,LWXPanelGetFunc (__cdecl *),LWXPanelSetFunc (__cdecl *))' : cannot convert parameter 4 from 'overloaded-function' to 'LWXPanelSetFunc (__cdecl *)' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 724
Warning 3 warning C4311: 'type cast' : pointer truncation from 'LWItemID' to 'int' c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 293
Warning 2 warning C4312: 'type cast' : conversion from 'int' to 'LWItemID' of greater size c:\documents and settings\luke whitehorn\my documents\cg\lightwave\lwsdk\sample\layout\displac ementmap\inertia\inertia.c 269


This is using the inertia plugin sample that comes with the sdk.
It seems that I can only get rid of such errors if my functions have the exact signature, i.e. a LWInstance structure as opposed to my own MyData structure. Do I just have to do a load of casting?

Lightwolf
10-01-2007, 04:39 AM
Do I just have to do a load of casting?
In a nutshell, yes.
The C code in the samples is valid ANSI C, however the behaviour has been deprectaed and C++ doesn't support it at all.

Cheers,
Mike

Anti-Distinctly
10-01-2007, 07:44 AM
In a nutshell, yes.
The C code in the samples is valid ANSI C, however the behaviour has been deprectaed and C++ doesn't support it at all.

Cheers,
Mike

So trying to use the inertia code (or other plugin) will not work if compiled as C++? :|
I did cast everything to what it was supposed to be in the inertia plugin, everything compiles fine, loads fine, but when I try to add the plugin I get this:


Cannot load external plug-in file <C:\Program Files\NewTek\...TAStab.p>.


Here's waht VS is telling me:


...
LWXPanel Info: Panel Hints Processing - Complete
LWXPanel Info: Panel Type Define - Begin
LWXPanel Info: Panel Type Define - DEF? no. GET? yes. SET? yes.
LWXPanel Info: Panel Type Define - Complete
'lightwav.exe': Loaded 'C:\Program Files\NewTek\LightWave 3D 9.3\Plugins\My Plugins\TAStab\debug\TAStab.p', Symbols loaded.
'lightwav.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.VC80.DebugCRT_1fc 8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c\msvcr80d.dll', Symbols loaded.
The thread 'Win32 Thread' (0x6c0) has exited with code 0 (0x0).
ihand node alloc exception!


I'm slowly going mad, but you are helping to slow the process :D

Anti-Distinctly
10-02-2007, 01:57 AM
Anyone? :\

Lightwolf
10-02-2007, 02:03 AM
Do you include the export.def in your project?

This tells the compŘiler to actually make _mod_descrip visible from the outside.

To check, open your .p file using depends.exe, _mod_descrip should be exported using a "C" signature.

Cheers,
Mike

Anti-Distinctly
10-02-2007, 10:53 AM
Dependency walker says that it's being exported as C, I think. This is the line I'm getting:
E-------Ordinal^-------Hint---------Function-------Entry Point
C-------1(0x0001)-------0(0x0000)-- _mod_descrip----0x00019144

Also, another interesting thing is that when I try to build the realease version, I get 83 errors and 29 warnings.
Debug version, I get 0 Errors 5 Warnings

I feel I'm losing my mind :(

Anti-Distinctly
10-02-2007, 11:06 AM
Renamed the lazyPoints.c file to lazyPoints.cpp and I now only get 19 errors and 4 warnings. Hmm.

Anti-Distinctly
10-03-2007, 01:01 PM
OK, that last one was my fault. Stupid mistake, the project settings were different for the release & debug builds. No errors now, but I'm still bashing my head against this...

Lightwolf
10-03-2007, 01:53 PM
OK, that last one was my fault. Stupid mistake, the project settings were different for the release & debug builds. No errors now, but I'm still bashing my head against this...
If you'd like to... send me your code and project and I'll have a quick look.

michael(dot)wolf(at)db-w(dot)com

Cheers,
Mike