Coder Social home page Coder Social logo

unreal-haskell-blueprint-tutorial's Introduction

Using Haskell + Stack with Unreal Engine 4 on Windows (Blueprint version)

(Source for the Unreal Engine part: https://wiki.unrealengine.com/Linking_Dlls)

  1. Create a project in UnrealEngine. I'm going to name it "HsDllTest"
    New project
  2. Go to the project folder, and create a folder. I will name it "Plugins".
    New directory
  3. Create a new stack project in it. I will call it "HsLib" and use the "simple-library" template:
    ...\HsDllTest\Plugins> stack new HsLib simple-library
  4. In the .cabal file, add this line: "ghc-options: -shared"
    New entry in the cabal file
  5. Paste this to Lib.hs:
{-# LANGUAGE ForeignFunctionInterface #-}

module Lib
    ( hsAdder
    ) where

import Foreign.C.Types

foreign export ccall hsAdder :: CInt -> CInt -> CInt

hsAdder :: CInt -> CInt -> CInt
hsAdder a b = a + b
  1. Use the stack build command to build the .dll file. (You'll find the "Lib_stub.h" file in ".stack-work/dist/????????/build", if you need it for something. Also note, that running stack build also creates a HsDlltest.dll.a file. It is a static library, but isn't necessary for our purposes.)
  2. Add a new C++ library to the Unreal Project. Choose "Blueprint Function Library". I will name it HsDllTestBFL
  3. Paste it into the "HsDllTestBFL.cpp" file:
// Fill out your copyright notice in the Description page of Project Settings.

#include "HsDllTest.h"
#include "HsDllTestBFL.h"

typedef int32(*_hsAdder)(int32 a, int32 b); // Declare a method to store the DLL method hsAdder.
typedef void(*_hs_init)(int* argc, char** argv);
typedef void(*_hs_exit)();

_hsAdder m_hsAdder;
_hs_init m_hs_init;
_hs_exit m_hs_exit;

void *v_dllHandle;

#pragma region Load DLL
// Method to import a DLL.
bool UHsDllTestBFL::importDLL(FString folder, FString name)
{
	FString filePath = *FPaths::GamePluginsDir() + folder + "/" + name;

	if (FPaths::FileExists(filePath))
	{
		v_dllHandle = FPlatformProcess::GetDllHandle(*filePath); // Retrieve the DLL.
		if (v_dllHandle != NULL)
		{
			return true;
		}
	}
	return false;	// Return an error.
}
#pragma endregion Load DLL

#pragma region Import Methods

bool UHsDllTestBFL::importMethod_hsAdder()
{
	if (v_dllHandle != NULL)
	{
		m_hsAdder = NULL;
		FString procName = "hsAdder";	// Needs to be the exact name of the DLL method.
		m_hsAdder = (_hsAdder)FPlatformProcess::GetDllExport(v_dllHandle, *procName);
		if (m_hsAdder != NULL)
		{
			return true;
		}
	}
	return false;	// Return an error.
}

bool UHsDllTestBFL::importMethod_hs_init()
{
	if (v_dllHandle != NULL)
	{
		m_hs_init = NULL;
		FString procName = "hs_init";	// Needs to be the exact name of the DLL method.
		m_hs_init = (_hs_init)FPlatformProcess::GetDllExport(v_dllHandle, *procName);
		if (m_hs_init != NULL)
		{
			return true;
		}
	}
	return false;	// Return an error.
}

bool UHsDllTestBFL::importMethod_hs_exit()
{
	if (v_dllHandle != NULL)
	{
		m_hs_exit = NULL;
		FString procName = "hs_exit";	// Needs to be the exact name of the DLL method.
		m_hs_exit = (_hs_exit)FPlatformProcess::GetDllExport(v_dllHandle, *procName);
		if (m_hs_exit != NULL)
		{
			return true;
		}
	}
	return false;	// Return an error.
}

#pragma endregion Import Methods

#pragma region Method Calls

int32 UHsDllTestBFL::hsAdder(int32 a, int32 b)
{
	if (m_hsAdder != NULL)
	{
		int32 out = int32(m_hsAdder(a, b)); // Call the DLL method with arguments corresponding to the exact signature and return type of the method.
		return out;
	}
	return -1;	// Return an error.
}

void UHsDllTestBFL::hs_init()
{
	if (m_hs_init != NULL)
	{
		m_hs_init(NULL, NULL); // Call the DLL method with arguments corresponding to the exact signature and return type of the method.
	}
}

void UHsDllTestBFL::hs_exit()
{
	if (m_hs_exit != NULL)
	{
		m_hs_exit(); // Call the DLL method with arguments corresponding to the exact signature and return type of the method.
	}
}

#pragma endregion Method Calls


#pragma region Unload DLL
// If you love something  set it free.
void UHsDllTestBFL::freeDLL()
{
	if (v_dllHandle != NULL)
	{
		m_hsAdder = NULL;
		m_hs_init = NULL;
		m_hs_exit = NULL;

		FPlatformProcess::FreeDllHandle(v_dllHandle);
		v_dllHandle = NULL;
	}
}
#pragma endregion Unload DLL
  1. Paste it into the "HsDllTestBFL.h" file:
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "HsDllTestBFL.generated.h"

/**
 * 
 */
UCLASS()
class HSDLLTEST_API UHsDllTestBFL : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
	public:

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static bool importDLL(FString folder, FString name);
	
	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static bool importMethod_hs_init();

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static bool importMethod_hs_exit();

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static bool importMethod_hsAdder();

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static int32 hsAdder(int32 a, int32 b);

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static void hs_init(); // Just give Null, Null as parameters. We call it as a lib, without using command line arguments

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static void hs_exit();

	UFUNCTION(BlueprintCallable, Category = "My DLL Library")
	static void freeDLL();
};
  1. Hit the compile button in the editor
  2. Create a blueprint class. I'll name it "HsDllActor"
  3. Create this blueprint:
    Blueprint
  4. Compile, and save. Drag it to the map, and press play. Relieve that it works.
    It works!

unreal-haskell-blueprint-tutorial's People

Contributors

spikeyarmaku avatar

Stargazers

Luis Daniel avatar  avatar Seb, The Layered Mind avatar Allen Dupras avatar Angel Castillo avatar Ashwin Mathi avatar  avatar Jessi Cady avatar Petr Dyachikhin avatar  avatar Vasiliy Yorkin avatar junji hashimoto avatar Anthony Raimondo avatar Josh Burgess avatar Yunis avatar Vsevolod Kvachev avatar Xiaoliang Zhang avatar

Watchers

Jessi Cady avatar  avatar Dennis Meckel avatar  avatar Yunis avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.