Actually it is very simple. As usual, we need to export the functions we are interested in to the Dynamic Library (DLL), and then import them into our C# program. Let's start.
C++ DLL
The first thing we need is to create a project in C++ for our future DLL, and of course configure it for the Leadwerks engine
Configuration for Release
Right-click on the project and select Property. In the window that appears, go to the tab "С/C++" / "General".
Copy and Paste to a "Additional Include Directories" this:
$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dgCore;$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dgNewton;$(LeadwerksHeaderPath)\Libraries\libvorbis\include;$(LeadwerksHeaderPath)\Libraries\libogg\include;$(LeadwerksHeaderPath)\Libraries\openssl\include;$(LeadwerksHeaderPath);$(LeadwerksHeaderPath)\Libraries\VHACD\src\VHACD_Lib\inc;$(LeadwerksHeaderPath)\Libraries\glslang;$(LeadwerksHeaderPath)\Libraries\freetype-2.4.7\include;$(LeadwerksHeaderPath)\Libraries\OpenAL\include;$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dMath;$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dgTimeTracker;$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dContainers;$(LeadwerksHeaderPath)\Libraries\NewtonDynamics\sdk\dCustomJoints;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\RecastDemo\Include;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\DetourCrowd\Include;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\DetourTileCache\Include;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\DebugUtils\Include;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\Recast\Include;$(LeadwerksHeaderPath)\Libraries\RecastNavigation\Detour\Include;$(LeadwerksHeaderPath)\Libraries\tolua++-1.0.93\include;$(LeadwerksHeaderPath)\Libraries/lua-5.1.4;$(LeadwerksHeaderPath)\Libraries/glew-1.6.0/include/GL;$(LeadwerksHeaderPath)\Libraries\glew-1.6.0\include;$(LeadwerksHeaderPath)\Libraries\enet-1.3.1\include;$(LeadwerksHeaderPath)\Libraries\zlib-1.2.5;$(LeadwerksHeaderPath)\Libraries\freetype-2.4.3\include;%(AdditionalIncludeDirectories)
Go to "Preprocessor", in "Preprocessor Definitions" copy and paste this:
WIN32;NDEBUG;LEADWERKS_EXPORTS;_WINDOWS;_USRDLL;PSAPI_VERSION=1;__STEAM__;_CUSTOM_JOINTS_STATIC_LIB;FT2_BUILD_LIBRARY;LEADWERKS_3_1;DG_DISABLE_ASSERT;WINDOWS;OS_WINDOWS;OPENGL;PLATFORM_WINDOWS;_WIN_32_VER;_NEWTON_USE_LIB;PTW32_STATIC_LIB;PTW32_BUILD;_NEWTON_STATIC_LIB;_LIB;DG_USE_NORMAL_PRIORITY_THREAD;GLEW_STATIC;_STATICLIB;%(PreprocessorDefinitions)
Go to "Code Generation". Set these values:
Enable Minimal Rebuild = Yes(/Gm)
Runtime Library = Multi-threaded (/MT)
Enable Function-Level-Linking = Yes (/Gy)
Go to "Precompiled Header" and set: "Not Using Precompiled Headers"
Now go to the "Linker" / "General" tab, then in "Additional Library Directories" copy and paste this:
$(LeadwerksLibPath)\Windows\x86;$(LeadwerksLibPath)\Windows\x86\Release;C:/Leadwerks\Engine\Source\Libraries\OpenAL/libs/Win32/EFX-Util_MT;C:/Leadwerks\Engine\Source\Libraries\OpenAL/libs/Win32;%(AdditionalLibraryDirectories)
Go to "Input", in "Additional Dependencies" copy and paste this:
newton.lib;dContainers.lib;dCustomJoints.lib;libcryptoMT.lib;libsslMT.lib;Rpcrt4.lib;crypt32.lib;libcurl.lib;Leadwerks.lib;msimg32.lib;lua51.lib;steam_api.lib;OpenAL32.lib;ws2_32.lib;libovr.lib;newton.lib;dContainers.lib;dCustomJoints.lib;OpenGL32.lib;Glu32.lib;winmm.lib;Psapi.lib;%(AdditionalDependencies)
Propery Sheet
Right-click on the project and select "Add \ New Item \ Property Sheets \ Property Sheet" click Add button.
Open it and paste this text:
Warning! Keep in mind that the paths may be different, check them out.
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros"> <LeadwerksHeaderPath>C:/Program Files (x86)/Steam/steamapps/common/Leadwerks\Include</LeadwerksHeaderPath> <LeadwerksLibPath>C:/Program Files (x86)/Steam/steamapps/common/Leadwerks\Library</LeadwerksLibPath> </PropertyGroup> <PropertyGroup /> <ItemDefinitionGroup /> <ItemGroup> <BuildMacro Include="LeadwerksHeaderPath"> <Value>$(LeadwerksHeaderPath)</Value> <EnvironmentVariable>true</EnvironmentVariable> </BuildMacro> <BuildMacro Include="LeadwerksLibPath"> <Value>$(LeadwerksLibPath)</Value> <EnvironmentVariable>true</EnvironmentVariable> </BuildMacro> </ItemGroup> </Project>
If all the paths match, you can import it into the project. Go to menu "VIEW / Other Windows / Property Manager"
Click button "Add Existing Property Sheet".
On this with the project settings everything =).
Now we can go directly to the code. This is part of the functions required for a simple program; you can add other functions yourself.
// Leadwerks.cpp : Defines the exported functions for the DLL application. // #include "Leadwerks.h" using namespace Leadwerks; #define EXPORT extern "C" __declspec(dllexport) // ---------------------------------------------------------------------------------- // SYSTEM // ---------------------------------------------------------------------------------- EXPORT void LE_System_Initialize() { System::Initialize(); } EXPORT void LE_System_Shutdown() { System::Shutdown(); } EXPORT void LE_System_SetAppName(const char* name) { System::AppName = name; } EXPORT void LE_System_SetAppPath(const char* path) { System::AppPath = path; } // ---------------------------------------------------------------------------------- // WINDOW // ---------------------------------------------------------------------------------- EXPORT Window* LE_Window_Create(HWND hwnd) { return Window::Create(hwnd); } EXPORT void LE_Window_Free(Window* window) { delete window; } EXPORT bool LE_Window_Closed(Window* window) { return window->Closed(); } EXPORT bool LE_Window_KeyHit(Window* window, int keycode) { return window->KeyHit(keycode); } // ---------------------------------------------------------------------------------- // CONTEXT // ---------------------------------------------------------------------------------- EXPORT Context* LE_Context_Create(Window* window) { return Context::Create(window); } EXPORT void LE_Context_Free(Context* context) { delete context; } EXPORT void LE_Context_Sync(Context* context, bool sync) { context->Sync(sync); } // ---------------------------------------------------------------------------------- // WORLD // ---------------------------------------------------------------------------------- EXPORT World* LE_World_Create() { return World::Create(); } EXPORT void LE_World_Free(World* world) { delete world; } EXPORT void LE_World_Update(World* world) { world->Update(); } EXPORT void LE_World_Render(World* world) { world->Render(); } // ---------------------------------------------------------------------------------- // CAMERA // ---------------------------------------------------------------------------------- EXPORT Camera* LE_Camera_Create() { return Camera::Create(); } EXPORT void LE_Camera_SetClearColor(Camera* camera, float r, float g, float b, float a) { camera->SetClearColor(r, g, b, a); }
Press "Ctrl+Shift+B"
C#
After a successful build, let's move on to C#.
Let's create a new project "Windows Forms App"
Here is the program code for an example:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace LETest { public partial class Form1 : Form { const string LEDLL = "Leadwerks.dll"; [DllImport(LEDLL)] public static extern void LE_System_Initialize(); [DllImport(LEDLL)] public static extern void LE_System_Shutdown(); [DllImport(LEDLL)] public static extern void LE_System_SetAppName(String name); [DllImport(LEDLL)] public static extern void LE_System_SetAppPath(String path); IntPtr window; [DllImport(LEDLL)] public static extern IntPtr LE_Window_Create(IntPtr hwnd); [DllImport(LEDLL)] public static extern void LE_Window_Free(IntPtr window); IntPtr context; [DllImport(LEDLL)] public static extern IntPtr LE_Context_Create(IntPtr window); [DllImport(LEDLL)] public static extern void LE_Context_Free(IntPtr context); [DllImport(LEDLL)] public static extern void LE_Context_Sync(IntPtr context, bool sync); IntPtr world; [DllImport(LEDLL)] public static extern IntPtr LE_World_Create(); [DllImport(LEDLL)] public static extern void LE_World_Free(IntPtr world); [DllImport(LEDLL)] public static extern void LE_World_Update(IntPtr world); [DllImport(LEDLL)] public static extern void LE_World_Render(IntPtr world); IntPtr camera; [DllImport(LEDLL)] public static extern IntPtr LE_Camera_Create(); [DllImport(LEDLL)] public static extern void LE_Camera_SetClearColor(IntPtr camera, float r, float g, float b, float a); Thread loopThread; bool isAppWork; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { isAppWork = true; loopThread = new Thread(EngineUpdate); loopThread.IsBackground = true; loopThread.Start(); } private void EngineUpdate() { //Initialize LE_System_Initialize(); window = LE_Window_Create(panel1.Handle); context = LE_Context_Create(window); world = LE_World_Create(); camera = LE_Camera_Create(); LE_Camera_SetClearColor(camera, 0.0f, 0.0f, 1.0f, 1.0f); //Main loop while (isAppWork) { LE_World_Update(world); LE_World_Render(world); LE_Context_Sync(context, true); } //Free LE_World_Free(world); LE_Context_Free(context); LE_Window_Free(window); LE_System_Shutdown(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { //isAppWork = false; loopThread.Abort(); loopThread = null; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { isAppWork = false; } } }
Copy you'r "DLL" to bin folder.
UPDATE:
Copy these file from you'r leadwekrs project to c# bin folder:
Shaders folder
dContainers.dll
dContainers_d.dll
dCustomJoints.dll
dCustomJoints_d.dll
libcurl.dll
lua51.dll
newton.dll
newton_d.dll
openvr_api.dll
steam_api.dll
- 2
16 Comments
Recommended Comments