Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Jabor
Jul 16, 2010

#1 Loser at SpaceChem
How are you building your plugin? How have you set things up so that your plugin glue code sees the functions it needs to call in the library?

Adbot
ADBOT LOVES YOU

mmkay
Oct 21, 2010

It'd probably help if you linked the library, so we can see how the example is built/configured.

Raenir Salazar
Nov 5, 2010

College Slice
Sure thing.

Triangle Library for CPP: https://github.com/mrkkrj/TrianglePP

For making the plugin I have my directories like this:

code:
Project:
    Plugins:
            TriangPPPlugin:
                Source:
                    ThirdParty:   // Source code
                        TrianglePPPluginLibrary:
                            include: // source files go here like tpp_interface.hpp
                            TrianglePPPLuginLibrary.Build.cs 
                    TrianglePPPlugin: // unreal module for interaction with rest of the project
                        Public & Private Folders
                        TrianglePPPlugin.Build.cs
TrianglePPPluginLibrary.Build.cs:
code:
using Microsoft.Extensions.Logging;
using System.IO;
using UnrealBuildTool;

public class TrianglePPPluginLibrary : ModuleRules
{
	public TrianglePPPluginLibrary(ReadOnlyTargetRules Target) : base(Target)
	{
		Type = ModuleType.CPlusPlus; // Either this or External both result in the same error

        // Add any include paths for the plugin
        PublicIncludePaths.AddRange(
            new string[] {
                    Path.Combine(ModuleDirectory, "include")
            }
        );
    }
}
TrianglePPPlugin.Build.cs
code:

using UnrealBuildTool;
using System.IO;
using Microsoft.Extensions.Logging;

public class TrianglePPPlugin : ModuleRules
{
    // The path to our Third Party code assets; e.g. ProjectFolder/ThirdParty/
    private string ThirdPartyPath
    {
        get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "..\\ThirdParty")); }
    }

    private string ThirdPartySourcePath
    {
        get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "..\\ThirdParty\\TrianglePPPluginLibrary\\include")); }
    }

    public TrianglePPPlugin(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
        bEnableExceptions = true;

		PrivateIncludePaths.AddRange(
			new string[] {
                "TrianglePPPlugin/Private"
            }
		);


        PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				"CoreUObject",
				"Engine",
				"TrianglePPPluginLibrary",
				"Projects" // Needed for IPluginManager?
			}
		);

        // Doesn't work either
        //PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "TrianglePPPluginLibrary", "include"));
    }
}
e to add:
My attempt to use it:
code:
// Copywrite info here?

#include "TrianglePPManager.h"

#include "TrianglePPPlugin.h"

// stl
#include <vector>

// Unreal
#include "Math/Vector2D.h"

// TrianglePP
THIRD_PARTY_INCLUDES_START
#include <tpp_interface.hpp>
THIRD_PARTY_INCLUDES_END

FTrianglePPManager& FTrianglePPManager::GetInstance()
{
    static FTrianglePPManager Instance;
    return Instance;
}

void FTrianglePPManager::TestFunc() 
{
	UE_LOG(LogTrianglePP, Log, TEXT("TestFunc()"));

    // prepare input
    std::vector<tpp::Delaunay::Point> delaunayInput;

    delaunayInput.push_back(tpp::Delaunay::Point(0, 0));
    delaunayInput.push_back(tpp::Delaunay::Point(1, 1));
    delaunayInput.push_back(tpp::Delaunay::Point(0, 2));
    delaunayInput.push_back(tpp::Delaunay::Point(3, 3));

    // 1. standard triangulation
    tpp::Delaunay trGenerator(delaunayInput); // errors here because it doesn't like dpoint
}
e2 to add error code transliterated from my phone as I don't have my laptop setup:
code:
Error LNK2019 unresolved external symbol "public: __cdecl tpp::Delaunay::Delaunay(class std::vector<class reviver::dpoint<double, 2>,class std::allocator<class reviver::dpoint<double,2>>> const &,bool)" 

Raenir Salazar fucked around with this message at 23:26 on Oct 21, 2023

mmkay
Oct 21, 2010

Both the QT test app and the example seem to add source/tpp_impl.cpp and source/tpp_assert.cpp plus all header files (in both the CMake and Visual Studio) when compiling an example. There's no static/dynamic library here, so the easiest way to do it is to also add these two files for the engine to build (ideally in a similar way by pointing to additional files to compile, so you're not just copying parts of the repo to your project, but rather have it as a submodule or something) - how to do it, I don't know, I've never used UE, I was just drawn into the thread by feeling a disturbance in the force and linker errors. :v:

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
basically, when you add the headers to the include directory, you're telling the compiler "hey here are some definitions for stuff that you can call, the actual implementations will be linked in later". and then you're not actually linking in the implementations.

one way to fix that is to compile the library code ahead-of-time into something that you can then link against. but another, easier way is to just compile the library code (like, all of the library code, not just the headers) at the same time as you compile the rest of your plugin code, instead of pulling it out as something that needs to be done separately.

Raenir Salazar
Nov 5, 2010

College Slice

Jabor posted:

basically, when you add the headers to the include directory, you're telling the compiler "hey here are some definitions for stuff that you can call, the actual implementations will be linked in later". and then you're not actually linking in the implementations.

one way to fix that is to compile the library code ahead-of-time into something that you can then link against. but another, easier way is to just compile the library code (like, all of the library code, not just the headers) at the same time as you compile the rest of your plugin code, instead of pulling it out as something that needs to be done separately.

Sounds promising, I tried including other headers before but maybe I missed one, to do this should I be including basically every file from the library directly in like MyManager.cpp or in the Build.cs:

code:
PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "TrianglePPPluginLibrary", "include", "filename.cpp"));
And just try literally including every file this way or is there a different way? Or is it including them directly with #include?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

Sounds promising, I tried including other headers before but maybe I missed one, to do this should I be including basically every file from the library directly in like MyManager.cpp or in the Build.cs:

code:
PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "TrianglePPPluginLibrary", "include", "filename.cpp"));
And just try literally including every file this way or is there a different way? Or is it including them directly with #include?
No, the word "include" pretty much consistently means it's talking about header files and is not how you get the linking done. There will be some other kind of configuration field, probably involving some variation of "library" or "link", into which you would add ideally library files (.a, .lib, .so, or .dll) but possibly cpp files.

#including all the cpp files somehow might be possible to get it to work but is absolutely horrific don't do it.

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

No, the word "include" pretty much consistently means it's talking about header files and is not how you get the linking done. There will be some other kind of configuration field, probably involving some variation of "library" or "link", into which you would add ideally library files (.a, .lib, .so, or .dll) but possibly cpp files.

#including all the cpp files somehow might be possible to get it to work but is absolutely horrific don't do it.

After massaging my search terms a little I found someone who had my exact same issue, and frustratingly not any answers.

https://forums.unrealengine.com/t/including-cpp-files-in-build-cs/317614/10

The closest I've seen is this reply:

quote:

Have you fixed the compiling error, @zapfdk? I uses a similar approach to yours (but I include all .cpp files in PCH header file after including the .h files in correct order, and wrap them inside a #ifndef #endif preprocessor), but when I compile it, I have double definition error.

Which sounds like the thing you're telling me not to do though?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

After massaging my search terms a little I found someone who had my exact same issue, and frustratingly not any answers.

https://forums.unrealengine.com/t/including-cpp-files-in-build-cs/317614/10

The closest I've seen is this reply:

Which sounds like the thing you're telling me not to do though?
Yeah, it might be that the problem is in the question - you generally wouldn't want to include cpp files, you'd want to link a library, which means building the library first. I don't use unreal so I can't give positive advice as to how you'd do that, I can only tell you that putting cc files in pch (which stands for precompiled *headers*) is absolutely not even close to the way you want to do it.

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

Yeah, it might be that the problem is in the question - you generally wouldn't want to include cpp files, you'd want to link a library, which means building the library first. I don't use unreal so I can't give positive advice as to how you'd do that, I can only tell you that putting cc files in pch (which stands for precompiled *headers*) is absolutely not even close to the way you want to do it.

Well I know how to include a library with a .lib/or dll, I've figured that out before despite how painful it was to figure out. The problem is I don't know how to compile a source code library into that. The example I found involved reimplementing the interface which I'm a little hesitant to do and the examples I found seemed outrageously complicated.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Raenir Salazar posted:

After massaging my search terms a little I found someone who had my exact same issue, and frustratingly not any answers.

https://forums.unrealengine.com/t/including-cpp-files-in-build-cs/317614/10

The closest I've seen is this reply:

Which sounds like the thing you're telling me not to do though?

Why do you think you want to do that?

Add the code to the project, or build a library and link it.

I wouldn't expect unreal to support unity builds. Which are generally terrible anyway.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Raenir Salazar posted:

Well I know how to include a library with a .lib/or dll, I've figured that out before despite how painful it was to figure out. The problem is I don't know how to compile a source code library into that. The example I found involved reimplementing the interface which I'm a little hesitant to do and the examples I found seemed outrageously complicated.

https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-static-library-cpp

Raenir Salazar
Nov 5, 2010

College Slice

leper khan posted:

Why do you think you want to do that?

Add the code to the project, or build a library and link it.

I wouldn't expect unreal to support unity builds. Which are generally terrible anyway.

Pardon? Did I mistype Unity somewhere? I looked but I don't think so unless I'm misunderstanding what you mean by "unity builds".

I'm trying to include a C++ Triangulation/Voronoi library that's a C++ wrapper for the C Triangle library.

"Adding code to the project" is what's... Not working? That's the whole problem, I made a plugin, I'm trying to add the code, and I'm getting unresolved external errors because Unreal doesn't seem to know how to find the Cpp files.

I DO know how to make a plugin that includes a library IF the library has a DLL/LIB, but I do not know how to make a static library from the source code.

Speaking of:


So my question here is, instead of manually reimplementing my library's version of "1+1=2" do I just include the interface header for the library in that file and call the methods inside the library "wrapper" methods? Can I return Objects like the "Delaunay" class or would it be probably easier to just return a bunch of arrays for the underlying data and resynch things into an object on the Unreal side of things?

Phigs
Jan 23, 2019

Raenir Salazar posted:

Pardon? Did I mistype Unity somewhere? I looked but I don't think so unless I'm misunderstanding what you mean by "unity builds".

It's a specific method of building C++ programs.

https://en.wikipedia.org/wiki/Unity_build

Raenir Salazar
Nov 5, 2010

College Slice

Phigs posted:

It's a specific method of building C++ programs.

https://en.wikipedia.org/wiki/Unity_build

Gotcha, I don't think that's what I'm trying to do though. I'll give another look at building a static library.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I haven't done any traditional coding in Unreal yet, but I suspect linkage is a pain in the rear end because you could end up building against multiple architectures. So I wouldn't be surprised if you have to specify linkage sources per target platform or something.

Raenir Salazar
Nov 5, 2010

College Slice

Rocko Bonaparte posted:

I haven't done any traditional coding in Unreal yet, but I suspect linkage is a pain in the rear end because you could end up building against multiple architectures. So I wouldn't be surprised if you have to specify linkage sources per target platform or something.

There is that option but its fairly easy in the build.cs files, you can specify what to do if win64 vs 32 or apple etc. I don't think that currently matters for me though.

blastron
Dec 11, 2007

Don't doodle on it!


Unreal actually does support unity builds. They’re very nice on large projects, but occasionally something fucks up somewhere and I waste two hours trying to figure out why something is failing to compile in my client build when the server build works just fine. I have a non-zero number of checkins that add whitespace to a comment in order to get the compiler to realize it missed a dependency somewhere.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

blastron posted:

Unreal actually does support unity builds. They’re very nice on large projects, but occasionally something fucks up somewhere and I waste two hours trying to figure out why something is failing to compile in my client build when the server build works just fine. I have a non-zero number of checkins that add whitespace to a comment in order to get the compiler to realize it missed a dependency somewhere.

I'm not sure I like the trade of shorter build farm builds for longer local incremental builds.

The C programmer in me is also terrified of collapsing translation units. Though I suppose that may matter less in a world where everything is contained in a class.

Does the linker still only cull at the translation unit level? So if you have
code:
some_unused();
next to
code:
main()
it won't strip the unused func?

blastron
Dec 11, 2007

Don't doodle on it!


leper khan posted:

I'm not sure I like the trade of shorter build farm builds for longer local incremental builds.

Ah, I may have been a little imprecise when I said “server” and “client” builds. We use incremental builds both locally and on the farm, with a nightly clean build. I meant that the build (both locally and on the farm) might fail differently when I’m compiling the binary for the game client and the binary for the game server, despite the code changes being identical on both of them.

No idea about translation units. Compilers terrify me and as soon as a build goes wrong in more than the most basic way I nuke everything and start from scratch.

Raenir Salazar
Nov 5, 2010

College Slice
So there's something I'm not sure about groking from trying to make a static library, if I create a static library, and link it in Unreal, will Unreal now "know" about the types? How minimal can I get away with making a static library if all I want is to be able to use the types/objects defined/implemented by the library do I need any code at all?

more falafel please
Feb 26, 2005

forums poster

Raenir Salazar posted:

So there's something I'm not sure about groking from trying to make a static library, if I create a static library, and link it in Unreal, will Unreal now "know" about the types? How minimal can I get away with making a static library if all I want is to be able to use the types/objects defined/implemented by the library do I need any code at all?

I think you're having trouble with the difference between declarations and definitions in C++. A declaration tells the compiler "this symbol (name) is a function/class/variable that looks like this", so the compiler knows what to do with it. Some examples of declarations:

C++ code:
void foo(int x);

class Bar 
{
public:
	void baz();
private:
	float y;
};

typedef std::vector<Bar> VectorOfBars;
Most of the time, definitions will be in header files.

A definition of a function is the actual compiled code:
C++ code:
void foo(int x)
{
	std::cout << x << std::endl;
}

void Bar::baz()
{
	std::cout << "Bar::baz()" << std::endl;
}
Definitions are typically in .cpp files. A .cpp file is often referred to as a "translation unit" and is compiled individually. Translation units typically include a number of header files, which tell the compiler that there are symbols defined ~somewhere else~ that that translation unit is able to reference. This means that in a.cpp, you can #include b.h and call a function that's defined in b.cpp, because everything the compiler needs to know to generate the code that calls that function is in the declaration in b.h. When a.cpp is compiled, the compiler doesn't worry about where that function is, it just puts a placeholder in and assumes it'll be there somewhere.

A build process (via a Visual Studio project, a Makefile, or Unreal's UBT) has some list of .cpp files to compile. It invokes the compiler on each of those, individually, and generates an object file of compiled machine code that exports symbols (names). So, foo.cpp compiles to foo.o (or foo.obj, depending on the compiler), bar.cpp -> bar.o, etc. If the target of the build is a shared or dynamic library, the build tool then invokes a "librarian" or "archiver" or something to that effect, which basically just dumps all the compiled object files into one file that now exports a bunch of symbols. If the target of the build is an executable, the build tool invokes the linker, which takes as input all the object files and libraries that need to be linked into the executable. The linker finds all those references to symbols that are defined ~somewhere else~, looks at all the symbols that are exported by all the object files and libraries, and fixes up all the locations, so that calling foo() will call that actual function.

You're seeing undefined symbol errors from the linker, which means that in at least one translation unit, you promised that there would be some function (or variable) called foo, and then when everything got compiled and was ready to link together, there was nothing by that name to be found. This means that either: you're not compiling the .cpp files that define those symbols, or you're not linking them in to the plugin DLL, or the game executable target isn't linking against that plugin DLL.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

leper khan posted:

Does the linker still only cull at the translation unit level? So if you have
code:
some_unused();
next to
code:
main()
it won't strip the unused func?
I'm pretty sure the VS linker culls at function-level since I've seen plenty of cases of it failing to set breakpoints in unused functions, but I have seen cases of it failing to cull unused vtables or something like that.

Raenir Salazar
Nov 5, 2010

College Slice
I mean I don't so, more falafel please, I understand the difference between implementation/definition and declaration, and you're describing the overall problem I'm having yes, but that isn't the difficulty I am currently having and I don't think was my question in the post you were responding to.

The solution I'm trying to figure out how to do is how to make a static library of the source code from github and to give it to Unreal. Which as I understand it is the only solution.

And the context of my question is, okay, I see a tutorial about how to make a static lib, but I have questions, such as can I still use the symbols as-is?

Here's what I ideally want, which is just be able to use the symbols from the library as-is inside Unreal.

(simplifying)
code:
#include "tpp_interface.hpp"
// just works magically because I somehow built a lib and passed it

// some Unreal class cpp file
void FTrianglePPManager::TestFunc() 
{
	UE_LOG(LogTrianglePP, Log, TEXT("TestFunc()"));

    // prepare input
    std::vector<tpp::Delaunay::Point> delaunayInput;

    delaunayInput.push_back(tpp::Delaunay::Point(0, 0));
    delaunayInput.push_back(tpp::Delaunay::Point(1, 1));
    delaunayInput.push_back(tpp::Delaunay::Point(0, 2));
    delaunayInput.push_back(tpp::Delaunay::Point(3, 3));

    // 1. standard triangulation
    tpp::Delaunay trGenerator(delaunayInput);
    ...
    // etc
}
The tutorial code for making a libary shows something like this:

code:
// MathLibrary.h
#pragma once

namespace MathLibrary
{
    class Arithmetic
    {
    public:
        // Returns a + b
        static double Add(double a, double b);

        // Returns a - b
        static double Subtract(double a, double b);

        // Returns a * b
        static double Multiply(double a, double b);

        // Returns a / b
        static double Divide(double a, double b);
    };
}
//
// MathLibrary.cpp
// compile with: cl /c /EHsc MathLibrary.cpp
// post-build command: lib MathLibrary.obj

#include "MathLibrary.h"

namespace MathLibrary
{
    double Arithmetic::Add(double a, double b)
    {
        return a + b;
    }

    double Arithmetic::Subtract(double a, double b)
    {
        return a - b;
    }

    double Arithmetic::Multiply(double a, double b)
    {
        return a * b;
    }

    double Arithmetic::Divide(double a, double b)
    {
        return a / b;
    }
}
Which is implementing a library and building it and spitting out a .lib file but isn't turning an existing chunk of source code INTO a library!

(Or do I just make a empty library project, add all the files from the library into the project and then hit build?)

So do I, as simply as possible, turn a folder of source files into a library so Scenario A can still be used?

Or is it like scenario B:

code:
#include "TrianglePPStaticLibrary.h"

using namespace tpp;
using Point = Delaunay::Point;

namespace TriangleLibrary
{
	Delaunay GetDelaunayFromPoints(std::vector<std::pair<double, double>>& Points)
	{
		std::vector<Delaunay::Point> delaunayInput;

		for (const auto& e : Points)
		{
			delaunayInput.push_back(Delaunay::Point(e.first, e.second));
		}

		Delaunay trGenerator(delaunayInput);
		trGenerator.Triangulate();
	}
}
Where I have to use the "Library" as a wrapper which will get me the data, but as I was considering this I was thinking, "Well wait, if I can get the data as the types I want, do I need the wrapper at all?" Can I just build the library? Which was the original question I was asking.

Or am I stuck with a very annoying and inefficient scenario C?

code:
namespace TriangleLibrary
{
	std::vector<std::pair> GetDelaunay2DFromPoints(std::vector<std::pair<double, double>>& Points)
	{
		std::vector<Delaunay::Point> delaunayInput;
		std::vector<std::pair> delaunayOutput;

		for (const auto& e : Points)
		{
			delaunayInput.push_back(Delaunay::Point(e.first, e.second));
		}

		Delaunay trGenerator(delaunayInput);
		trGenerator.Triangulate();

                // do some loops
                return delaunayOutput;
	}
}
Where I use it as a wrapper but have to interact with it with STL containers because Unreal will never have any means of knowing the types?

Scenario A, B or C? Was my question.

e: edit to fix code blocks and clear up my question.

e2: Also or am I grossly overthinking this process and why I'm getting stuck?

Raenir Salazar fucked around with this message at 15:07 on Oct 23, 2023

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

Scenario A, B or C? Was my question.
Should be scenario A. You need the headers in an include path Unreal knows about (which you configure) so it can find them, and the library in a link path (which you configure) or with its location fully explicit (again, in Unreal config somewhere).

Usually it would be more like #include "tpp_library/tpp_interface.hpp" or #include "tpp_library/include/tpp_interface.hpp" or something like that, relative to a configured include path, because having all the files right *directly* in an include path makes you more likely to have filename conflicts (utility.h is everywhere!)

BabelFish
Jul 20, 2013

Fallen Rib

blastron posted:

Unreal actually does support unity builds. They’re very nice on large projects, but occasionally something fucks up somewhere and I waste two hours trying to figure out why something is failing to compile in my client build when the server build works just fine. I have a non-zero number of checkins that add whitespace to a comment in order to get the compiler to realize it missed a dependency somewhere.

I too have spent half a day figuring out why the heck adding single lines of comments are breaking my build in a seemingly completely un-related file written and maintained by a different engineer.

If you're ending up with unity build failures, it's usually because you're missing an include somewhere that's being hidden by the fact that the unity build is smashing headers into one uber-header and the include you need just happens to be there. Ideally you should be able to compile without unity builds and still get a functioning build. It's a good thing to check occasionally.

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

Should be scenario A. You need the headers in an include path Unreal knows about (which you configure) so it can find them, and the library in a link path (which you configure) or with its location fully explicit (again, in Unreal config somewhere).

Usually it would be more like #include "tpp_library/tpp_interface.hpp" or #include "tpp_library/include/tpp_interface.hpp" or something like that, relative to a configured include path, because having all the files right *directly* in an include path makes you more likely to have filename conflicts (utility.h is everywhere!)

Well I made a library:



I just dump in all of the files and clicked build, I got a Lib file, a chunky 3mb which seemed promising; which I included into my project, but I'm getting the same error. :(

My build.cs files being as before.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

I just dump in all of the files and clicked build, I got a Lib file, a chunky 3mb which seemed promising;
This looks good and seems good so far.

quote:

which I included into my project, but I'm getting the same error. :(
So "included into my project" is probably where it's going wrong. If I recall correctly you were getting link errors - two likely things here, either the lib is not included in the right piece of config, so it's not actually being linked at all, or the lib is being built with a different kind of name-mangling than the project, so it can't find the function names it expects. I'd get the full function name (including stupid decoration chars) from the link error and grep for it in the lib file, to check for the mangling thing.

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

This looks good and seems good so far.

So "included into my project" is probably where it's going wrong. If I recall correctly you were getting link errors - two likely things here, either the lib is not included in the right piece of config, so it's not actually being linked at all, or the lib is being built with a different kind of name-mangling than the project, so it can't find the function names it expects. I'd get the full function name (including stupid decoration chars) from the link error and grep for it in the lib file, to check for the mangling thing.

Bearing in mind I'm constantly commenting/uncommenting and moving things around trying to brute force something to work.

Build.cs for the Plugin:

code:
public class TrianglePPPlugin : ModuleRules
{
    // The path to our Third Party code assets; e.g. ProjectFolder/ThirdParty/
    private string ThirdPartyPath
    {
        get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "..\\ThirdParty")); }
    }

    private string ModulePath
    {
        get { return ModuleDirectory; }
    }

    private string LibrariesPath
    {
        get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "..\\..\\Libs")); }
    }

    public TrianglePPPlugin(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
        bEnableExceptions = true;

		PrivateIncludePaths.AddRange(
			new string[] {
                "TrianglePPPlugin/Private"
            }
		);

        PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				"CoreUObject",
				"Engine",
				"TrianglePPPluginLibrary",
				"Projects" // Needed for IPluginManager?
			}
		);

        PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "TrianglePPStaticLibrary.lib"));

        PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "TrianglePPPluginLibrary", "include"));

        Logger.LogInformation("My ThirdPartyPath: {0}", Path.Combine(ThirdPartyPath, "TrianglePPPluginLibrary", "include"));
        Logger.LogInformation("My Libraries: {0}", LibrariesPath);

    }
}
Build.cs for the Library:

code:
public class TrianglePPPluginLibrary : ModuleRules
{
	public TrianglePPPluginLibrary(ReadOnlyTargetRules Target) : base(Target)
	{
		Type = ModuleType.CPlusPlus;

        // Add any include paths for the plugin
        PublicIncludePaths.AddRange(
            new string[] {
                Path.Combine(ModuleDirectory, "include")
            }
        );

        PublicAdditionalLibraries.Add(Path.GetFullPath(Path.Combine(PluginDirectory, "Libs", "TrianglePPStaticLibrary.lib")));

        Logger.LogInformation("Test: {0}", Path.Combine(ModuleDirectory, "include"));
        Logger.LogInformation("Library Location: {0}", Path.GetFullPath(Path.Combine(PluginDirectory, "Libs", "TrianglePPStaticLibrary.lib")));
    }
}
I opened the lib file in Notepad and found 3 hits for both errors:

code:
LNK2019	unresolved external symbol "public: __cdecl tpp::Delaunay::Delaunay(class std::vector<class reviver::dpoint<double,2>,class std::allocator<class reviver::dpoint<double,2> > > const &,bool)" (??0Delaunay@tpp@@QEAA@AEBV?$vector@V?$dpoint@N$01@reviver@@V?$allocator@V?$dpoint@N$01@reviver@@@std@@@std@@_N@Z) referenced in function "public: void __cdecl FTrianglePPManager::TestFunc(void)" (?TestFunc@FTrianglePPManager@@QEAAXXZ)

LNK2019	unresolved external symbol "public: __cdecl tpp::Delaunay::~Delaunay(void)" (??1Delaunay@tpp@@QEAA@XZ) referenced in function "public: void __cdecl FTrianglePPManager::TestFunc(void)" (?TestFunc@FTrianglePPManager@@QEAAXXZ)
Usage:
code:
#include "TrianglePPManager.h"

#include "TrianglePPPlugin.h"

// stl
#include <vector>

// Unreal
#include "Math/Vector2D.h"

// TrianglePP
//THIRD_PARTY_INCLUDES_START
#include "tpp_interface.hpp"
//THIRD_PARTY_INCLUDES_END

FTrianglePPManager& FTrianglePPManager::GetInstance()
{
    static FTrianglePPManager Instance;
    return Instance;
}

void FTrianglePPManager::TestFunc() 
{
	UE_LOG(LogTrianglePP, Log, TEXT("TestFunc()"));

    // prepare input
    std::vector<tpp::Delaunay::Point> delaunayInput;

    delaunayInput.push_back(tpp::Delaunay::Point(0, 0));
    delaunayInput.push_back(tpp::Delaunay::Point(1, 1));
    delaunayInput.push_back(tpp::Delaunay::Point(0, 2));
    delaunayInput.push_back(tpp::Delaunay::Point(3, 3));

    // 1. standard triangulation
    tpp::Delaunay trGenerator(delaunayInput); // errors with this
}

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

I opened the lib file in Notepad and found 3 hits for both errors:
code:
LNK2019	unresolved external symbol "public: __cdecl tpp::Delaunay::Delaunay(class std::vector<class reviver::dpoint<double,2>,class std::allocator<class reviver::dpoint<double,2> > > const &,bool)" (??0Delaunay@tpp@@QEAA@AEBV?$vector@V?$dpoint@N$01@reviver@@V?$allocator@V?$dpoint@N$01@reviver@@@std@@@std@@_N@Z) referenced in function "public: void __cdecl FTrianglePPManager::TestFunc(void)" (?TestFunc@FTrianglePPManager@@QEAAXXZ)
So just to confirm, you're saying this exact string
code:
??0Delaunay@tpp@@QEAA@AEBV?$vector@V?$dpoint@N$01@reviver@@V?$allocator@V?$dpoint@N$01@reviver@@@std@@@std@@_N@Z
appears in your lib file?

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

So just to confirm, you're saying this exact string
code:
??0Delaunay@tpp@@QEAA@AEBV?$vector@V?$dpoint@N$01@reviver@@V?$allocator@V?$dpoint@N$01@reviver@@@std@@@std@@_N@Z
appears in your lib file?

Yes.

Raenir Salazar
Nov 5, 2010

College Slice
OH MY loving GOD.

*throws computer into a lake*

Problem was between the monitor and the chair, when I copied the Lib file over to my project, I put it into Binaries where I had accidentily put the previous Lib file I had made, and not the Libs FOLDER which is where I'm actually linking!

I now have two entirely DIFFERENT errors! But it's progress!

C4703, potentially uninitialized local pointer variable, which I'll google in a second and hopefully this isn't because the original author of the code did something weird.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Ahhh the old "put the file in this specific folder to own the libs."

Raenir Salazar
Nov 5, 2010

College Slice

Rocko Bonaparte posted:

Ahhh the old "put the file in this specific folder to own the libs."

chmod 777

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Raenir Salazar posted:

C4703, potentially uninitialized local pointer variable, which I'll google in a second and hopefully this isn't because the original author of the code did something weird.
That one's pretty cool because it's actually a warning, and you're presumably just compiling with warnings as errors, so you're almost good to go. I mean the whole thing is going to be a loving nightmare I'm sure, but you're probably past the build problems stage and into the code problems stage.

Raenir Salazar
Nov 5, 2010

College Slice

roomforthetuna posted:

That one's pretty cool because it's actually a warning, and you're presumably just compiling with warnings as errors, so you're almost good to go. I mean the whole thing is going to be a loving nightmare I'm sure, but you're probably past the build problems stage and into the code problems stage.



IT SUCCEEDS!! :cry:

I went into the Library project, disabled SDL checks, recompiled, recopied my Lib file over, and it WOOOOOORKS!!!

Thanks y'all for your help, it let me keep going along the right direction.

e:

code:
LogTrianglePP: TestTriangulatePoints()
LogTrianglePP: Face Coordinates: (X=0.000 Y=2.000), (X=0.000 Y=0.000), (X=1.000 Y=1.000).
LogTrianglePP: Face Coordinates: (X=1.000 Y=1.000), (X=3.000 Y=3.000), (X=0.000 Y=2.000).
YESSSSSSSSSSSSSSSSSSSS!

Raenir Salazar fucked around with this message at 03:30 on Oct 24, 2023

Blue Footed Booby
Oct 4, 2006

got those happy feet

blastron posted:

Unreal actually does support unity builds. They’re very nice on large projects, but occasionally something fucks up somewhere and I waste two hours trying to figure out why something is failing to compile in my client build when the server build works just fine. I have a non-zero number of checkins that add whitespace to a comment in order to get the compiler to realize it missed a dependency somewhere.

Unreal Engine supports Unity. Cool, cool, makes perfect sense. :shepicide:

DrZepam
Mar 15, 2021

Blue Footed Booby posted:

Unreal Engine supports Unity. Cool, cool, makes perfect sense. :shepicide:

TObjectPtr<MonoBehaviour> Unreal5SupportsUnity; // MAKES PERFECT SENSE

Joke aside, maybe OP meant Unity Technologies have their live-ops services (that they purchased) in the UE Marketplace (live iron source, Plastic SCM, etc..)

Frosty Mossman
Feb 17, 2011

"I Guess Somebody Fixed All the Problems" -- Confused Citizen
Or maybe they meant the thing that was talked about and even clarified with a wikipedia article just a couple of posts before.

Phigs posted:

It's a specific method of building C++ programs.

https://en.wikipedia.org/wiki/Unity_build

Adbot
ADBOT LOVES YOU

pseudorandom name
May 6, 2007

Frosty Mossman posted:

Or maybe they meant the thing that was talked about and even clarified with a wikipedia article just a couple of posts before.

You can't expect programmers to read the game development thread, they have real jobs that pay well for reasonable hours.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply