ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.6k stars 598 forks source link

[GoldSrc] Compiling smdlexp.dle -> unresolved externals #1529

Closed thefoofighter closed 10 years ago

thefoofighter commented 10 years ago

Hi,

I managed to get MAX4.2 sdk and i eradicated most of the bugs for smdlexp but now i have come across one that stumps me.

1>smdlexp.obj : error LNK2019: unresolved external symbol "declspec(dllimport) public: thiscall CStr::CStr(wchar_t const )" (imp_??0CStr@@QAE@PB_W@Z) referenced in function "protected: void thiscall SmdExportClass::VariantToString(struct tagPROPVARIANT const ,char *,int)" (?VariantToString@SmdExportClass@@IAEXPBUtagPROPVARIANT@@PADH@Z)

I understand that this error typically means you are missing a reference to a library. I am just not sure which one it is :(

Any help here would be greatly appreciated.

Thank you

dtugend commented 10 years ago

I can't tell what exactly is going on, because I don't know what you have modified in SmdExportClass::VariantToString in smdlexp.cpp.

I am assuming the following is happening: 1) The TSTR macro is mapping to the 3DS Max class CStr, see here for more info about the macros here! 2) You are passing a wide string wchar_t * to the CStr constructor (TSTR macro). 3) The 3DS Max SDK probably accidentally provides a class declaration for a CStr constructor for wchar_t *, but most likely they didn't define (implement) that constructor, because it shouldn't be needed (because using the macros you should select the right class).

To fix this check if you are using a String literal in that function (i.e. "hello" or more likely L"hello") and make sure that you are using the conversation macros appropriately (either see the 3DS Max doc link above or see here).

If you modified the function, posting the result here would be helpful.

Also please let us know which Microsoft Visual Studio version you are using and which project files (which file name in the halflife SDK source tree) you opened with it. If you are using the vcxproj files, I cannot guarantee that I did no mistake when converting them manually from the dsp files. However I payed extra attention to that MCBS/UNICODE stuff, but as said I am just human, so maybe the problem is on my end.

dtugend commented 10 years ago

I think it's a problem with the code in SmdExportClass::VariantToString in smdlexp.cpp and the SDK u are using. Are you really using MAX SDK 4.2?

I think the problem is in line 1050: _tcscpy(szString, TSTR(pProp->pwszVal));

TSTR should translate to CStr in the default project settings and I am assuming that the SDK you use declares it for the wchar_t * type but does not implement it (at least that constructor for wchar_t * is not documented in newer SDKs. Sadly you cannot simply replace it with WStr, because WStr has no operator that casts to char const * (meaning you would get a different problem), at least none that is documented.

Waiting for your reply :-)

Edit: To make it compile you could change that line 1050 to s.th. similar to:

_tcscpy(szString,
    (WStr(pProp->pwszVal))
#ifndef _UNICODE
    .ToCStr()
#endif
);

However it would only compile for your Setup then, because all Lines using TSTR "inappropriately" in that code listing would need to be fixed, so that the code compiles for _UNICODE too.

thefoofighter commented 10 years ago

Hi ripieces,

Thank you kindly for your replies :) I actually modified very little of the SDK, I was really just trying to compile everything to see it it worked and in the sake of stubbornness when I couldn't get the smdlexp to compile I kept at it.

Things I did have to do and did change are as follows: I had to find the MAX4.2 SDK (which turned out being closer to home than expected) I had to find Physique (PHYEXP.H which I found on the net) I had to find CTL3D.DLL as it complained about this too (also found it on the webs)

Other than that i had 2 errors pertaining to undeclared identifiers for 'inm' and 'irn' at two separate parts in smdlexp.cpp

I'm not quite sure why VS complained about this but Curly braces enclosing the for loops seem to have done the trick. -> might this be part of the error?

Then upon compile I get the error I asked about originally.

I hope you can bare with me as I am not a great programmer by any means. I am using Visual Studio 2013 which works fine for the rest of the solutions and compiles and debugs HL.DLL without any problems.

I opened halflife-master\projects\vs2010\utils.sln in VS2013 and let it convert it automatically (It did a pretty good job)

I could try if you like to open up the a fresh utils.sln in VS2010 Express, it may help in some way?

Also I am positive I am using MAX4.2 and it accompanying SDK including the update from the CD. I cannot however run MAX4.2 because of incompatibilities with WIN7 64bit. So even if I compile this successfully I wont be able to test it, Unless i create a sandbox OS of WIN XP 32bit (lots of work :P)

So yes I may be wasting your time, I am sorry, It may though help someone else in the future :) And i am always curious as to why things are not working when they should :)

I attempted your fix above and maybe I am thick but it wont compile, It cannot find .ToCStr() It complains about not having a member function as well as it not being found anywhere in the project after a search.

Might i be missing something?

Thank you again for your support Much appreciated

Cathal

dtugend commented 10 years ago

I'm not quite sure why VS complained about this but Curly braces enclosing the for loops seem to have done the trick. -> might this be part of the error?

This is not part of the error. This is because earlier Visual Studio C++ versions extended the scope of identifiers defined in the for loop beyond the scope of the for loop (to the scope of the block the for-loop was defined in. Meaning in earlier versions you could do this:

for(int test=0;test<10;test++)
{
}

printf("Test is: %i", test);

In newer C++ Versions they changed it (how it should be) to being valid in the scope of the for loop only. Meaning the code above will give you a compile error. The correct way to port the old code to the new code is defining the identifiers used outside of the loop before the loops begins:

int test;
for(test=0;test<10;test++)
{
}

printf("Test is: %i", test);

Please be extra careful when fixing this, because if you do this wrong and just add some braces somewhere, you might accidentally change the meaning of the code.

I should have fixed those "errors" already when creating the .vcxproj files, but since I couldn't compile it without the MaxSDK 4.2 I didn't notice them.


Since I don't have your Max SDK 4.2 I am bound to guessing:

I am guessing that while you have the headers (.h) of Max SDK 4.2 which don't have .ToCStr() yet, you are having / using the libraries (.lib) files of a newer SDK than 4.2 which don't have the old wchar_t * constructors.

Please first make sure (in case you have more than one SDK installed), that the library folder is pointing to the SDK 4..2 and not a different one: To check this right click the smdlexp Project in the Solution Explorer, select Properties, then go to The Linker tree node and one of the sub-nodes (i.e. General) should have "Additional Library Directories" in the properties panel. Make sure that there is no directory set that points to a newer SDK directory (only the old one).

If that doesn't solve your problem test if you are using a newer library than your header files:

Make a backup of your strclass.h in the Max 4.2 SDK. The open the file in C++ an search where there is s.th. defined like

class WStr {
// ....
}

And add the following member function definition to the class definition:

CStr ToCStr () const;

Then save the file and see if my suggested fix (using ToCStr) compiles or not. If it does it means the headers you are using and the libraries you are using are not compatible, as suggested above. Alternatively you could use a hex editor and open the .lib files in question (core.lib and maxutil.lib) and search for ToCStr, but that might be a bit confusing due to name mangling.

While on the way, also look if the class CStr defined in strclass.h (or a included file) contains a constructor for wchar_t *, meaning look if it has a line as follows:

class CStr {
// ....
CStr(wchar_t const * someName);
// ....

PS: In case you want to contact me for some reason by other means, my e-mail is linked on the homepage linked in my github account profile.

thefoofighter commented 10 years ago

Hi,

Thank you for clearing the forloop thing up , I have corrected my edits.

So i think you are right that my headers are not compatible :( What a shame. I added the toCStr() definition above but it complains about unresolved externals in CStr:Cstr(wchar_t const *) still

Checking the definition it does differ slightly to what you have above UtilExport CStr(const wchar_t *wcstr);

I wonder at this point that since my SDK doesnt have the necessary files to compile successfully should we bother pursuing this? There could be a mountain of incompatibles...

Also very hard to find the MAX 4.2 SDK on the internet :(

Thank you for the support Cathal

dtugend commented 10 years ago

Did you edit Line 1050 to use WStr as I suggested in my second post, before testing?

Also instead of adding

CStr ToCStr () const;

Make that Please:

UtilExport CStr ToCStr () const;

Also I checked that the 3DS Max SDK 2012 didn't have that to ToCStr stuff yet, if it works then you got the libraries of i.e. 2013 or newer?

(Please post the exact error message from the console window, in case you get one.)

dtugend commented 10 years ago

We found the problem: Back in Visual C++ 5.0/6.0 wchar_t was not a built-in type and instead defined as unsigned short. That results into a different name mangling, which is why the compiler can't find the constructor in the old libraries (.lib). Setting the compiler switch /Zc:wchar_t- fixes the problem, since then in the project the wchar_t type will be mapped to unsigned short as it was in the early days, meaning it will be found in the MAX SDK 4.2 maxutil.lib correctly.

@thefoofighter and me are working on a fix, that we will try to push within the next few hours.

thefoofighter commented 10 years ago

Yay it works :) There is one other small fix to submit that will make the actual plugin work with max 4.2 tested on my end and the model exported, compiled perfectly and looks good in Jeds viewer :)

working with @ripieces on it