I would like to use a C# DLL in an Android Project that is developing by Java (Not Xamarin or Mono).
My first strategy to solve this contains these steps:
Create a C++ usable DLL by DllExport from the C# code. (create a C++ wrapper for C# code)
Create a .so library from the C++ project that uses generated DLL from the previous step.
So I've used the DLLExport (https://github.com/3F/DllExport)
C# Side:
namespace NumbersLibCS
{
public class Math
{
public Math()
{
}
[DllExport]
public static int GetRandomEvenNumber()
{
var rnd = new Random();
int n = rnd.Next(1, 1000 ) * 2;
return n;
}
}
}
But in C++ to use the generated DLL I think I should use just windows.h library that is not available on the Android OS:
#include <windows.h>
typedef int(__cdecl *GetRandomEvenNumber)();
int main(){
HMODULE lib = LoadLibrary("mycsharp.dll");
auto getRndNumber= (GetRandomEvenNumber)GetProcAddress(lib, "GetRandomEvenNumber");
int c = getRndNumber();
}
Now here are my questions:
How can I use DLLExport generated DLL without windows.h?
Can I use .NetCore 2.0 to achieve this without using DLLExport?
Related
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 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());
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'm trying to call some Windows basic functions from C#, in particular this one.
Since the moment I want to learn the C++/CLI Language too, I've written down this code:
#pragma once
#include <string>
#include <Windows.h>
using namespace System;
namespace InformazioniSchermo {
public class Native_InformazioniDaSistema
{
public:
int m_nAltezzaPannello;
int m_nLarghezzaPannello;
Native_InformazioniDaSistema(void)
{
DISPLAY_DEVICE dd;
DWORD dev = 0;
dd.cb = sizeof(dd);
EnumDisplayDevices(0, dev, &dd, 0);
m_nAltezzaPannello = 100;
m_nLarghezzaPannello = 100;
}
};
public ref class InformazioniDaSistema
{
public:
InformazioniDaSistema();
~InformazioniDaSistema();
public:
int m_nHeight;
int m_nWidth;
};
InformazioniDaSistema::InformazioniDaSistema()
{
Native_InformazioniDaSistema foo;
m_nHeight = foo.m_nAltezzaPannello;
m_nWidth = foo.m_nLarghezzaPannello;
}
InformazioniDaSistema::~InformazioniDaSistema()
{
}
}
but when I compile, I get this error:
Error 3 error LNK2028: at unresolved token (0A0003B4) "extern "C" int __stdcall EnumDisplayDevicesW(wchar_t const *,unsigned long,struct _DISPLAY_DEVICEW *,unsigned long)" (?EnumDisplayDevicesW##$$J216YGHPB_WKPAU_DISPLAY_DEVICEW##K#Z) referencing in function "public: __thiscall InformazioniSchermo::Native_InformazioniDaSistema::Native_InformazioniDaSistema(void)" (??0Native_InformazioniDaSistema#InformazioniSchermo##$$FQAE#XZ) c:\Users\massimiliano\documents\visual studio 2013\Projects\InformazioniSchermo\InformazioniSchermo\InformazioniSchermo.obj InformazioniSchermo
Where am I doing wrong?
You need to link against user32.lib (the library for the EnumDisplayDevices function, as you'll see in the MSDN page you linked to).
You can do this by going to project properties->Linker->Input and adding user32.lib to the "Additional Dependencies" list.
I notice that the default Visual Studio project settings for C++/CLI don't include the common Windows API libraries by default (regular C++ projects have kernel32.lib, user32.lib, shell32.lib and others added to the project's library dependencies in new projects) so you have to add these libraries yourself if you're using them.
error LNK2028: ... (?EnumDisplayDevicesW##$$J216YGHPB_WKPAU_DISPLAY_DEVICEW##K#Z) ...
That is the name the linker is looking for. That is not it's name, it is a C function and does not have the C++ name mangling. Pretty unclear how you did that, especially since you obfuscated your #includes. But the only reasonable guess is that you declared this function yourself instead of using its declaration in the SDK header.
Never do that. Instead use:
#include <Windows.h>
#pragma comment(lib, "user32.lib")
With the #pragma helpful so you can't forget to link to user32
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.