After a long reading time I didn't get the dll working...
I tried so much different ways but no way worked..
I did the following things: (IDE: VS2013Ultimate)
I added a clean c++ project. There I added 1 header file [header.h]:
#pragma once
class myClass{
public:
myClass(double varx, double vary);
double sumxy();
private:
double x;
double y;
};
I added a body.cpp file:
#pragma once
#include "header.h"
myClass::myClass(double varx, double vary){
x = varx;
y = vary;
}
double myClass::sumxy(){
return x + y;
}
That's all the code I would need. I only want a working example code.
I added one class [main.cpp]:
#include "header.h"
#include "body.cpp"
extern "C" __declspec(dllexport) double sumxy(double var_x, double var_y){
myClass MC(var_x, var_y);
return MC.sumxy();
}
After this I compiled this dll and I got it without any compile errors. `I copied it to the debug folder of the c# Console Application
C# Console Application:
using System.Runtime.InteropServices;
//all using directories
namespace Klassen_Tester {
class Program {
[DllImport("CppClassDll.dll")]
public static extern double sumxy(double var_x, double var_y);
static void Main(string[] args) {
Console.WriteLine(sumxy(3, 5).ToString());
Console.ReadLine();
}
}
}
Please help me. Don't know what to do.. And sorry for my bad english.
Edit: There is an error: System.DllNotFoundException in Klassen_Tester.exe. DLL "CppClassDll.dll" could not be found. HRESULT: 0x8007007E) could not be load.
You might consider using an interop between C++ and C# so you don't have to mess with pinvoke. I'm not saying pinvoke is bad but interops are nice.
You are going to want to write a CLR wrapper to act as an intermediary between the managed and unmanaged code. It looks like you have the C# and C++ mostly written so I'll describe the CLR portion.
Create a CLR project in Visual Studio
Add your native C++ project as a reference
Write your wrapper
Add reference to CLR project from C# project
Call CLR wrapper
Create a class with your C++ signatures likes this:
namespace YourWrapper
{
public ref class WrappedFunction
{
public:
// Adjust according to your c++ class and function
double sumxy(double a, double b) {
return myClass::sumxy(a, b);
}
};
}
For a full example, see my project https://github.com/corytodd/interop-example:
Related
I am trying to create a dynamic library .so using CUDA C++ kernel to use it inside C# code under Linux environment (CentOS). I searched for a way yo do this, but unfortunately didn't find a complete clear solution for it. Some solutions only make partial part of it, like creating C++ shared library on Linux, or creating chain of libraries in CUDA using nvcc, but there was no method for creating a dynamic library from CUDA C++. The using of .so created from C++ seamed possible like in this solution.
Is there a way to create this dynamic library and use it successfully inside C# code?
After searching multiple different solutions, and trying to collect and test the available possibilities, I finally reached to this simple method.
The original C++ library can be made using gcc in one step like this answer.
gcc -shared -o dll.so -fPIC dllmain.cpp
but make sure to add extern "C" before the required function(s) inside .cpp file, like this:
#include <stdio.h>
extern "C" void func()
{
// code
}
For CUDA C++, nvcc can be used in the same way similarly to this answer and this answer combined. Make sure to use .so instead of .dll and use the proper device architecture, I used 60 here as I am using "Tesla P100-PCIE-16GB".
nvcc -arch=sm_60 --compiler-options '-fPIC' -o dll.so --shared kernel.cu
The .cu file will be similar to this.
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
extern "C" void myfunc(int a, int b, ...);
__global__ void kernel(int a, int b, ...);
__global__ void kernel(int a, int b, ...)
{
int i = threadIdx.x;
// kernel code
}
void myfunc(int a, int b, ...)
{
// code
}
Now the dynamic library .so is created and can be used inside C# code like this.
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("dll.so")]
static extern myfunc(int a, int b, ...);
private void Method()
{
int a, b;
// code
myfunc(a, b, ...);
}
}
The C# code then is compiled using Mono.
mcs Program.cs
mono Program.exe
But it will probably be necessary to set the path of the used library like this.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library/
This worked for a simple CUDA C++ code, it will likely work for other ones, but some problems may arise depending on their complexity.
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).
I am very new to the .NET platform (coming from the JVM and having some limited C/C++ experience) and trying my first managed C++ class library. This is to serve as a bridge to a third-party DLL I got and I have to interface. I tried it with BridJ and Java but had no success so far, so I am now trying to write the program which uses the third-party DLL in C#.
The third-party DLL is unmanaged C++.
My ManagedBridge.h so far looks similar to this:
#pragma once
#include "thirdparty.h"
using namespace System;
namespace ManagedBridge {
class __declspec(dllexport) BridgedThirdPartyThing {
private:
THIRDPARTYNS::ThirdPartyThing* _delegate;
public:
BridgedThirdPartyThing();
~BridgedThirdPartyThing();
void foo();
// more methods
};
}
My ManagedBridge.cpp so far looks like this:
#include "stdafx.h"
#include "ManagedBridge.h"
namespace ManagedBridge {
BridgedThirdPartyThing::BridgedThirdPartyThing() {
_delegate = new THIRDPARTYNS::ThirdPartyThing();
}
BridgedThirdPartyThing::~BridgedThirdPartyThing() {
delete _delegate;
}
void BridgedThirdPartyThing::foo() {
_delegate -> foo();
}
// similar for the other methods
}
}
Now, when I build this, I get no errors, and a ManagedBridge.dll is created.
I then created a C# Console application to test my DLL, added it as a reference, but I cannot access the class I exported with __declspec(dllexport). Only the namespace is shown in the object browser.
What am I missing?
It's
public ref class BridgedThirdPartyThing
for C++/CLI. You don't use __declspec(dllexport). Note that the class needs to be public to be visible to comsuming assemblies.
I'm pretty new to DLLs and the sort. I've got the following DLL written in C++:
Dll.cpp
#include "pch.h"
#include "Dll.h"
namespace ns {
double Cpp_class::cppAdd(double a, double b)
{
return a + b;
}
}
Dll.h
#pragma once
#ifndef Dll_h
#define Dll_h
namespace ns{
class Cpp_class sealed /* this is what makes your class visible to managed code */
{
public:
static double cppAdd(double a, double b);
};
}
#endif
I took the code from the following link in order to test out some DLLs (just tweaked it a bit):
How to import C++ dll in Windows Phone Project
The problem is with this line:
ns.Cpp_class.cppAdd(1,3);
I get the following error: A namespace cannot directly contain members such as fields or methods. Could anyone tell me how I can access the function cppAdd from a C# app after "using Dll"?
(Note: Dll project has been correctly referenced, I simply do not know how to call the function from the C# app)
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...