Unmanaged C++ wrapper for C# usage - c#

SOLVED: Thanks to Casey Price for their answer. I then ran into 2 other errors: BadImageFormatException and FileNotFoundException, the former was solved by matching the platform target (x64 or x86) for each project and the latter was solved by setting the output directory of the C# project to the directory containing the dll file.
I'm working on a game 'engine' which currently has a working graphics subsystem that draws/textures movable models. I'm trying to write a C++/CLR wrapper so I can use the engine in a C# program (as a designer tool).
My wrapper project is a C++/CLR class library and contains the following 2 files (as well as resource.h/cpp and Stdafx.h/cpp)
// pEngineWrapper.h
#pragma once
#define null NULL
#include "..\pEngine\pEntry.h"
using namespace System;
namespace pEngineWrapper
{
public ref class EngineWrapper
{
public:
EngineWrapper();
~EngineWrapper();
bool Initialise();
private:
pEntry* engine;
};
}
and the .cpp file
// This is the main DLL file.
#include "stdafx.h"
#include "pEngineWrapper.h"
pEngineWrapper::EngineWrapper::EngineWrapper()
{
engine = null;
}
pEngineWrapper::EngineWrapper::~EngineWrapper()
{
delete engine;
engine = null;
}
bool pEngineWrapper::EngineWrapper::Initialise()
{
bool result;
engine = new pEntry;
result = engine->Initialise();
if( result == false )
{
return false;
}
return true;
}
When I go to build this project however I get 14 errors: LNK2028, LNK2019, and LNK2001 which points to some classes within the engine. I have included the errors in the file below.
https://www.dropbox.com/s/ewhaas8d1te7bh3/error.txt?dl=0
I also get a lot of warnings regarding XMFLOAT/XMMATRIX which you may notice.
In all of the engine classes I use the dllexport attribute
class __declspec(dllexport) pEntry
I feel like I'm missing the point and doing it all wrong seeing all of these errors but I haven't found any documents telling me anything considerably different than what I'm doing here

you have to add a reference to the static .lib files for the game engine you are using as well as it's dll's or load the dll's manually
to add the references to the .lib files right click your project->Properties->Linker->input add the lib file to the additional dependencies
See also: DLL References in Visual C++

Related

Calling native Win32 code from .NET (C++/CLI and C#)

I'm developing an app for C#, and I want to use DirectX (mostly Direct2D) for the graphical component of it. So I'm trying use use C++/CLI as an intermediary layer between the native C++ code and the managed code of C#. So far a have 3 projects in my solution: A C# project (which I won't really discuss since it's not giving me any problems yet), a C++ static library that includes Windows.h, and a dynamic C++/CLI library that's intended to marshal information between the other two projects. Here is my code so far:
In the native C++ project, I have a class named RenderWindowImpl that so for only contains 2 methods:
//RenderWindowImpl.h
#pragma once
#include <Windows.h>
class RenderWindowImpl final
{
public:
RenderWindowImpl() = default;
~RenderWindowImpl() = default;
int test();
private:
static void InitializeWin32Class();
};
// RenderWindowImpl.cpp
#include "RenderWindowImpl.h"
int RenderWindowImpl::test()
{
return 5;
}
void RenderWindowImpl::InitializeWin32Class()
{
WNDCLASSEXW wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = nullptr;
wc.hInstance = GetModuleHandleW(0);
wc.hCursor = LoadCursorW(nullptr, IDC_ARROW);
//wc.lpszClassName = L"wz.1RenderWindowImpl";
//// TODO: error check
//RegisterClassExW(&wc);
}
And in my C++/CLI project, I have a class named RenderWindow that acts as a wrapper around RenderWindowImpl:
// wzRenderWindow.h
#pragma once
//#pragma managed(push, off)
#include "RenderWindowImpl.h"
//#pragma managed(pop)
using namespace System;
namespace wzRenderWindow {
public ref class RenderWindow sealed
{
public:
RenderWindow();
~RenderWindow();
int test();
private:
RenderWindowImpl* impl;
};
}
// wzRenderWindow.h.
#include "stdafx.h"
#include "wzRenderWindow.h"
wzRenderWindow::RenderWindow::RenderWindow()
{
// Initialize unmanaged resource
impl = new RenderWindowImpl();
try
{
// Any factory logic can go here
}
catch (...)
{
// Catch any exception and avoid memory leak
delete impl;
throw;
}
}
wzRenderWindow::RenderWindow::~RenderWindow()
{
// Delete unmanaged resource
delete impl;
}
int wzRenderWindow::RenderWindow::test()
{
return impl->test();
}
When I compile my project, I get the following warnings and errors:
Error LNK1120 1 unresolved externals wzRenderWindow d:\documents\visual studio 2015\Projects\WizEngCS\Debug\wzRenderWindow.dll 1
Warning LNK4075 ignoring '/EDITANDCONTINUE' due to '/OPT:LBR' specification wzRenderWindow d:\documents\visual studio 2015\Projects\WizEngCS\wzRenderWindow\wzRenderWindowImpl.lib(RenderWindowImpl.obj) 1
Error LNK2019 unresolved external symbol __imp__LoadCursorW#8 referenced in function "private: static void __cdecl RenderWindowImpl::InitializeWin32Class(void)" (?InitializeWin32Class#RenderWindowImpl##CAXXZ) wzRenderWindow d:\documents\visual studio 2015\Projects\WizEngCS\wzRenderWindow\wzRenderWindowImpl.lib(RenderWindowImpl.obj) 1
It seems to be the call to LoadCursorW that C++/CLI doesn't like, as the code compiles fine if I comment out that line. With the Win32 function calls removed, I was able to successfully call RenderWindow::test() from a C# application, outputting the expected result of 5.
I'm a bit of a loss because my understanding of C++/CLI is that it's very good at wrapping native C++ classes for consumption by managed .NET applications. I would really like to understand why my code is not compiling.
As a related follow-up question, am I barking up the wrong tree here? What's the conventional way to access DirectX methods (or similar COM-based C/C++ libraries) from .NET? I'd like to avoid using 3rd-party wrapper libraries like SharpDX.
I fixed the problem by putting #pragma comment(lib, "User32.lib") at the top of my RenderWindowImpl.cpp. Thanks to #andlabs for the fix. I'm not sure why this fixed the problem (I've never needed to explicitly link to user32.lib in any of my previous projects).

Dynamically load a C# .NET assembly in a C++Builder application

I have a C++ Windows application developped with RAD Studio (C++Builder) XE4. It has some plugins, which are DLLs (always written with RAD Studio) that are dynamically loaded with this technique.
Now in one of this plugins I need reflection capabilities. While it seems I cannot achieve them with C++ (reflection is needed on a third-party COM DLL that I cannot modify) I decided to rewrite this plugin in C# (which has powerful reflection capabilities), thus creating a .NET assembly.
I know I should expose the assembly via COM, but I can't (we don't want to change the way the main application loads all DLLs).
My aim is to dynamically load the .NET assembly and invoke its functions (for instance here we call SetParam function) with something like the following, like I do with the other plugins.
//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/assembly.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "_SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());
where ptr_SetParam is defined as
typedef int(*ptr_SetParam)(const wchar_t*, const wchar_t*);
Is there a way?
Thanks to #HansPassant's comment I found a way.
I created following Visual Studio projects.
MyDllCore .NET assembly project, written in C# or any other .NET language. Here I have my managed class like the following, where the real logic of the assembly is implemented.
using System;
using System.Collections.Generic;
//more usings...
namespace MyNamespace
{
public class HostDllB1
{
private Dictionary<string, string> Parameters = new Dictionary<string, string>();
public HostDllB1()
{
}
public int SetParam(string name, string value)
{
Parameters[name] = value;
return 1;
}
}
}
MyDllBridge DLL project, written in C++/CLI, with /clr compiler option. It is just a "bridge" project, it has a dependancy on MyDllCore project and has just one .cpp o .h file like the following, where I map the methods from the program that loads the DLL to the methods in the .NET assembly.
using namespace std;
using namespace System;
using namespace MyNamespace;
//more namespaces...
#pragma once
#define __dll__
#include <string.h>
#include <wchar.h>
#include "vcclr.h"
//more includes...
//References to the managed objects (mainly written in C#)
ref class ManagedGlobals
{
public:
static MyManagedClass^ m = gcnew MyManagedClass;
};
int SetParam(const wchar_t* name, const wchar_t* value)
{
return ManagedGlobals::m->SetParam(gcnew String(name), gcnew String(value));
}
Finally I have a C++Builder program that loads MyDllBridge.dll and uses its methods calling them like in the following.
//load DLL
HINSTANCE handleDll = LoadLibraryW("C:/Path/to/the/MyDllBridge.dll");
//get reference to the function
void* ptr = GetProcAddress(handleDll, "SetParam");
ptr_SetParam ptrFunc = reinterpret_cast<ptr_SetParam>(ptr);
//invoke function
int result = (*ptrFunc)(String("mykey").c_str(), String("myvalue").c_str());

Creating a CPP DLL for use in a C# program

So I have a WPF solution. I added a new project and added a CPP Dll project to it.
I used this example. Pretty straight forward.
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
Here is my code
CppTestDll.cpp
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
When I build this I do in fact get a DLL
Now when I go into my WPF app and attempt to add a reference to this DLL I get this error.
"A reference to 'C:\DIR\testcppdll.dll' could not be added. Please
make sure that the file is accessible, and that it is a valid assembly
or COM component."
If you look in the example you cite:
Creating a simple C# application:
Start Visual Studio .NET. Go to File->New->Project.
Select Visual C#
Project. ... (you can select WPF Project)
Give the name to your application. Press OK. Into the specified
class, insert the following two lines:
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
In C#, keyword extern indicates that the method is implemented externally.
Your code should look something like this:
using System;
using System.Runtime.InteropServices; // DLL support
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
public void SomeFunction()
{
Console.WriteLine ("This is C# program");
DisplayHelloFromDLL ();
}
}
You don't add a reference to the to the DLL - you P/Invoke the Function using DLLImport

How to make CUDA dll that can be used in C# application?

It would be good if you could give me a brief tutorial instead of a few words.
My CUDA application is working as I wanted. Now, the problem is how to export CUDA code to C# as I would like to make front end and everything else in C#.
From this link:
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
I know how to make a library in C language that can be imported into C# application as Win32 dll.
But my question is, how to make CUDA application dll (or some other extension) that can be shipped to C# and used from C# application?
It would be good if there is somewhere tutorial for CUDA like the one for C library to C# app(above link).
I am using Win7 64 bit, Visual Studio 2010 Ultimate, Cuda Toolikt 5.0 and NSight 2.2.012313
ManagedCUDA is perfect for this type of thing. First you need to follow the instructions in the documentation to set up your Visual Studio Project.
Here is an example of a solution:
test.cu (compiles to test.ptx)
#if !defined(__CUDACC__)
#define __CUDACC__
#include <host_config.h>
#include <device_launch_parameters.h>
#include <device_functions.h>
#include <math_functions.h>
#endif
extern "C"
{
__global__ void test(float * data)
{
float a = data[0];
float b = data[1];
float c = data[2];
data[0] = max(a, max(b, c));
}
}
and here is the C# code:
private static void Test()
{
using (CudaContext ctx = new CudaContext())
{
CudaDeviceVariable<float> d = new CudaDeviceVariable<float>(3);
CUmodule module = ctx.LoadModulePTX("test.ptx");
CudaKernel kernel = new CudaKernel("test", module, ctx)
{
GridDimensions = new dim3(1, 1),
BlockDimensions = new dim3(1, 1)
};
kernel.Run(d.DevicePointer);
}
}
This is just a proof of concept, the device memory is not even initialized and the result is not read but is enough to illustrate how to do it.
You have several options how to distribute your application. In this case i opted for compiling the .cu file into PTX and load it inside the C# project from filesystem.
You could also embed the PTX as a resource directly into your C# application.
You could also compile into a cubin and load or embed that instead of PTX.

Export c++ functions inside a C# Application

Greetings,
I am sorry for bothering, I'll show the question:
I am trying to export some functions written in c++ in a DLL in order to import them in a C# Application running on Visual Studio.
I make the export as reported in the following code,
tobeexported.h:
namespace SOMENAMESPACE
{
class __declspec(dllexport) SOMECLASS
{
public:
SOMETYPE func(param A,char b[tot]);
};
}
tobeexported.cpp:
#include "stdafx.h"
#include "tobeexported.h"
...
using namespace SOMENAMESPACE;
SOMETYPE SOMECLASS:: func(param A,char b[tot])
{
...some stuff inside...
}
The dll is righly created and the code is already CLR-managed(looked with a disassembling software(reflector)) and contains the exported functions
then I "Add the Reference" in my c# application and the dll is found, but when
I open it with the object browser it is completely empty, neither class, nor object has been exported and ready to be used
can you help me please?
thanks
best regards
What about using managed C++ to compile your DLL? Then you just have to add a ref to the class like this:
namespace SOMENAMESPACE
{
public ref class SOMECLASS
{
public:
SOMETYPE func(param A,char b[tot]);
};
}
After successful compilation and referencing in the other project, the class should be visible. Exporting native C++ is not really portable, each compiler produces different results and is tedious to bind from within C#...
EDIT: added public access modifier to ref class...

Categories