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
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.
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:
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.
Below is my code in c#...
here callback is too implemented in c# only.
i want a callback from c++ dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
class Program
{
// [DllImport("C:/Users/kool/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)]
static void Main(string[] args)
{
function1(function2); // i want thia function2 to be fetched from ++ dll
}
public delegate void fPointer(); // point to every functions that it has void as return value and with no input parameter
public static void function1(fPointer ftr)
{
fPointer point = new fPointer(ftr);
point();
}
public static void function2()
{
Console.WriteLine("Bla");
}
}
i will createa a dLL from where i will send function2 to
function1(function2);
how can i implement it??
One way is exporting the C# assembly as a type library and using it from C++ as if it were a COM component.
Use TlbExp.exe in the Visual Studio command prompt to export the C# assembly as a type library. Then register the type library with RegAsm.exe. Then in the C++ code use the #import directive to import the type library. You can now use the C# classes from C++ as if they were COM classes.
For more detail see: http://msdn.microsoft.com/en-us/library/ms172270.aspx
Edit: Sorry, which is it that you want to do: use C++ from C#, or use C# from C++?
Either one is possible. The link above explains how to use C# from C++. This one explains how to use C++ from C#: http://msdn.microsoft.com/en-us/library/z6tx9dw3.aspx
You can send pointer to your managed .net function and call it from unmamaged code (callback).
Detail here http://habrahabr.ru/post/130690/ (use google to translate it from russian if needed, but you need to look at last two code example).
Also check your code calling - it should comply on both managed and unmanaged sides (use __stdcall in C-code and CallingConvention = CallingConvention.Cdecl in DllImport attribute).
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...