Jump to content

Help needed - compile a .cpp file into a .dll


Recommended Posts

Hello.

 

I'm trying to revive the fantastic mod "Clipboard" (https://www.nexusmods.com/fallout4/mods/31090?tab=posts), which has sadly been abandoned since July 2018. The author "Struckur" has provided the source code and a header file which hopefully means that it can be recompiled but I have absolutely no idea where to start.

 

I searched on the net and downloaded MS VisualStudio, then MinGW and Codeblocks but have no idea what to do next.

 

I did some ansi C back in the early eighties but this newfangled C++ stuff is way beyond me and even setting up the compiler tools these days is a complete mystery to me.

 

If anyone can give me any help it would be greatly appreciated.

 

 

 

Link to comment
Share on other sites

  • Replies 64
  • Created
  • Last Reply

Top Posters In This Topic

1. Install Visual Studio Community Edition.

You'll need Desktop Development with C++. Also install Windows 8.1 SDK from Individual Components page (I don't know if is required).


2. Download latest F4SE version (currently this is 0.6.17) and unzip the archive.

3. Load f4se_0_06_17\src\f4se\f4se.sln solution.

4. It may complain that the projects are for an older version, so retarget them. Ignore f4se_loader, f4se_loader_common and f4se_steam_loader, you don't need them.


Now make some changes. Right click on f4se project => select properties => make sure that All Configurations is selected. Then:


1. Change the Configuration Type from Dynamic Library to Static Library (General page)

2. Remove the Post Built event for F4SE project (from Build Events page)


You may also need to:


1. Add #include <algorithm> to PapyrusObjects.h

2. Add #include <xmmintrin.h> to BSSkin.h (but I think this is not required anymore)


Select the desired configuration (Debug or Release) from toolbar and then ... BUILD THE PROJECT (Build\Build Solution menu)


If it works then you successfully compiled F4SE and this is the first step.

If it doesn't work ... bad luck.

Edited by Wolfmark
Link to comment
Share on other sites

Hi Wolfmark, and many thanks for the help.

 

I ran through your instructions to the letter and I believe it worked.

 

I couldn't find PapyrusObjects.h or BSSkin.h, so I just skipped that bit and went straight to BUILD.

 

I got errors about f4se_loader_common.vcxproj and f4se_steam_loader.vcxproj, but you said they don't matter so hopefully that's OK.

 

I ended up with the following files -

 

f4se_1_10_138.dll

f4se_1_10_138.exp

f4se_1_10_138.iobj

f4se_1_10_138.ipdb

f4se_1_10_138.lib

f4se_1_10_138.pdb

f4se_common.lib

 

...in the folder C:\Users\Kev\Downloads\f4se_0_06_17\src\f4se\x64\Release\

 

Hopefully that means that it worked?

Link to comment
Share on other sites

If you got the DLL then yes, it worked. Beginner's luck :smile:

 

Unload those 3 loader projects: right click on them and select Unload Project option. You don't need them.

PapyrusObjects.h is in f4se_0_06_17\src\f4se\f4se folder (or select f4se project from left tree, then papyrus\vm folder).

BSSkin.h is also in the same folder (or select f4se project from left tree, then netimmerse folder).

But it seems that there's no need to edit them anymore.

 

To compile a F4SE extension you must copy it to f4se_0_06_17\src\f4se folder. Each extension should be in his own folder, next to F4SE default projects:

f4se_0_06_17\src\f4se\

  • extension1
  • extension2
  • f4se
  • f4se_common
  • f4se_loader
  • etc...

The problem is that while Struckur released the source code, he/she didn't release the project file (the vcxproj file). This means that you'll have to create it.

Remember, in Visual Studio there's a solution (f4se.sln) that contains one or more projects (*.vcxproj).

 

I'll post the details later (after I do some tests).

Edited by Wolfmark
Link to comment
Share on other sites

To create a the project for your extension:


1. Right click on f4se solution (on the root, not on the project that has same name) and select Add => New Project.

2. Select Visual C++ => Windows Desktop => Dynamic-Link Library (DLL). Set the name to clipboard (or whatever) and make sure that the location is f4se_0_06_17\src\f4se. Click OK.

3. Right click on the new project and select Set as Startup Project (and the name should now be displayed with bold). This will be the main project.

4. Remove all *.cpp and *.h generated files (should be 5 files). Use the DELETE option, to remove them from harddisk too. Or use REMOVE and then delete them manually from harddisk.

5. In project's folder (harddisk) you should now have only 2 or 3 files: clipboard.vcxproj, clipboard.vcxproj.filters and clipboard.vcxproj.user (this one may be missing).

6. Copy the main.cpp file from github (or from the archive with source file) to project's folder.

7. Now right click on project's Source Files folder, select Add, Existing Item and select the main.cpp file.


Remember, extension's folder must be next to f4se, f4se_common, f4se_loader etc...


Then update project's references:


1. Right click on References, select Add Reference and then select f4se_common and f4se projects. You may also select the common_vc11 project, but probably is not required.


Then time to change project's settings. Right click on project's name and select Properties.


Make sure that "All Configurations" is selected:


1. Change General \ Character Set to Multi-Byte Character Set (must match the one used by f4se default projects).

2. Set C/C++ => General page => Additional Include Directories to "$(SolutionDir);$(SolutionDir)\.." (without quotes!!!)

3. Set C/C++ => Precompiled Headers => Precompiled Header to inherit from parent => it will automatically change to Not Using Precompiled Headers on save.

4. Set C/C++ => Advanced => Forced Include File to "common/IPrefix.h" (without quotes!!!)

5. Set C/C++ => Language => Conformance Mode to inherit from parent (will change to No when saved).


Then you'll need to change some settings that have different values for Debug & Release, so you can't do this while having All Configurations selected. First select Debug, do the change, then select Release and do the change again.


1. Add _CRT_SECURE_NO_WARNINGS to the list with preprocessor definitions (C/C++ => Preprocessor => Preprocessor Definitions) (they are separated using ; character)

2. Change C/C++ => Code Generation => Runtime Library to Multi-threaded (for Release configuration) and Multi-threaded Debug (for Debug configuration).


Unfortunately this mod requires changes to GameReferences.h file from f4se project. You can't use the file from clipboard mod because is based on an older F4SE version, so you'll have to re-apply the changes.


1. Open the GameReferences.h file from f4se project => api folder.

2. Replace unk104 and unk108 with scale, unk10A and unk10C.

3. Add the definition for SetScale function.


See https://imgur.com/OS2E0Mt for details. Let's hope that the address (0x003F8490) didn't change, otherwise you'll have to find it (and this requires other skills). From what I see the addresses for the other functions from same class are the same since F4SE 0.6.10 (the oldest version I have on harddisk), so it should work.

Edited by Wolfmark
Link to comment
Share on other sites

Note that the code seems to be buggy.
Building the extension using Debug configuration results in a list of warnings/errors which can't be ignored:
1. warning C4172: returning address of local variable or temporary
To fix this edit the GetLogFilePath, GetSettingFilePath, GetDefaultSettingFilePath functions and replace "std::string &" with "std::string" (remove the & character from signature).
2. error C4703: potentially uninitialized local pointer variable 'generatedPowerInfo' used
The original code:
if (form && form->formType == ActorValueInfo::kTypeID)
    generatedPowerInfo = (ActorValueInfo *)form;
The fixed code:
if (form && form->formType == ActorValueInfo::kTypeID)
    generatedPowerInfo = (ActorValueInfo *)form;
else return;

 

Link to comment
Share on other sites

WOW some fantastic footwork you did for me there Wolfmark, and I really really appreciate the help, many thanks.

 

I can't wait to get to trying it out , but sadly I'll have to wait until later this evening (Berlin time) or even tomorrow as my day is completely full today.

 

Those code changes look Chinese to me, I really don't understand them at all lol. It's like a passenger trying to land a 747 by radio guidance, but I'm certainly willing to try :D.

 

Regards.

Link to comment
Share on other sites

OK, spent the evening going through all your instructions and I managed to get all the way through to the bit about error C4703!

 

If I build with your modified code -

if (form && form->formType == ActorValueInfo::kTypeID)
    generatedPowerInfo = (ActorValueInfo *)form;
else return;

...it spits out pages of errors (click here for text file), if I leave it as original then I only get the one error C4703.

 

I searched the net for "error C4703", and most answers talked about generatedPowerInfo not being properly initialised (initialising inside an "if") and confusing the compiler, and a solution would be to set generatedPowerInfo to nullptr to trick it.

 

I tried several combinations of setting it to null but still got the 83 errors :smile:.

 

 

EDIT:

 

Maybe it has something to do with a setting I got wrong somewhere -

 

common_vc11.lib(IDebugLog.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in clipboard-dll.obj

 

common_vc11 is set to 'MTd_StaticDebug', and clipboard-dll is set to 'MDd_DynamicDebug'?

 

I searched but couldn't see where to change that setting.

Link to comment
Share on other sites

You compiled the code. The errors are from linker.

If you leave the code unmodified => compilation fails => you'll see only one error.

If you fix the code => compilation succeeds => you'll see many errors, but from the linker, not from compiler.

 

It seems that the result (main.obj) is incompatible with what resulted after compilation of f4se projects (f4se, f4se_common and common_vc11), so the linker can't create the final DLL file.

The first errors are caused by an invalid value for Runtime Library setting. Read my message again, you must set this to Multi-threaded Debug for Debug configuration and Multi-threaded for Release configuration.

Change this, verify again all the other options, recompile and see if it works.

 

LE: also verify that you set the dependencies for your project; see the part about references, I assume you also skipped this because of "unresolved external symbol" errors

Edited by Wolfmark
Link to comment
Share on other sites

I changed a few of those settings and it actually compiled a clipboard.dll - but the file was really small (72kb when the last version was 5443kb!). I tried it out but it didn't work.

 

Tomorrow I'll delete everything and start again from scratch, but this time I'll stop when I don't understand or can't find something and ask your advice and wait before proceeding instead of trying to figure things out myself (which obviously doesn't work!).

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...