Some questions about C++/CLI and C# integration - c#

Good night,
I was trying to make a simple dll in C++/CLI to use in my c# library using something like the following code:
// This is the main DLL file.
#include "stdafx.h"
namespace Something
{
public class Tools
{
public : int Test (...)
{
(...)
}
}
}
I can compile the dll and load it into the C# project without any problems, and can use the namespace Something and the class Tools from C#. The problem is that when I try to write Tools.Test(something) I get an error message saying that Tools doesn't have a definition for Test. Why can't the compiler get the function, even if it is declared public?
Also... Can I share a class across two project, half written in C# and half written in managed C++?
Thank you very much.

C# can only access managed C++ classes. You would need to use public ref class Tools to indicate that Tools is a managed class to make it accessible from C#. For more info see msdn.
This class can then be used in either managed C++ or C#. Note that managed C++ classes can also use native C++ classes internally.

You can share a managed class across a project, but what you've written in an unmanaged (i.e. standard C++ class. Use the ref class keyword to define a managed class in C++.
// This is the main DLL file.
#include "stdafx.h"
namespace Something
{
public ref class Tools
{
public : int Test (...)
{
(...)
}
}
}

The function is not static. try this in the
var someTools = new Tools();
int result = someTools.Test(...);
or make the method static :
public :
static int Test (...)
{
(...)
}

Related

Use C++ class in C# with strings (Dll)

I am trying to use my C++ class in my C# program. So I made a .dll-file to use it in C#. My problem is, that I am working with strings. My question is: How can I return a std::string to my C# program?
My C++ class (header-file):
using namespace std;
class CComPort
{
public:
string ReadLine();
void WriteLine(string userInput);
};
My dll code:
string CppWrapper::CComPortWrapper::ReadLineWrapper()
{
return comPort->ReadLine();
}
void CppWrapper::CComPortWrapper::WriteLineWrapper(string userInput)
{
comPort->WriteLine(userInput);
}
My C#-Code:
comPort.WriteLineWrapper(tb_send.Text);
Error:
'CComPortWrapper.WriteLineWrapper(?,?)' is not supported by the language.
I tried to change the dll file to something like this, but it didn't worked:
void CppWrapper::CComPortWrapper::WriteLineWrapper(String ^ userInput)
{
comPort->WriteLine(userInput);
}
What is the rigth way to change it?
It appears that you're wrapping a class used just for serial port communication. There are ways of accessing the serial port directly from C#, without needing C++/CLI. Unless there's a lot of logic in the C++ class that cannot be ported/would be hard to port to C#, please do consider doing the serial communication in C#.
You haven't shown us the declaration of your CComPortWrapper class. I'm assuming that it's public ref class CComPortWrapper.
If the goal of your wrapper is to make it callable from managed languages (e.g., C#), then you should use managed types in your declaration.
In this case, you should declare the methods of CComPortWrapper to take & return System::String^. Within the wrapper, convert it to/from std::string, and call the unmanaged class with that.
I recommend using marshal_as to do the conversion, especially since you're converting from one class to another. You don't need to deal with explicitly allocating memory or anything like that; let each string class manage its own memory, and let marshal_as deal with copying & converting the data.
#include <msclr\marshal_cppstd.h>
using namespace System;
String^ CppWrapper::CComPortWrapper::ReadLineWrapper()
{
std::string result = comPort->ReadLine();
return marshal_as<String^>(result);
}
void CppWrapper::CComPortWrapper::WriteLineWrapper(String^ userInput)
{
std::string input = marshal_as<std::string>(userInput);
comPort->WriteLine(input);
}

make c++ class in a native dll to use in C#

I spent about 3 days reading about this topic...
I am totally lost now thanks to the many tutorials and answered questions about how to create a native DLL. If you have some time to spare please care to explain a little about the topic and help me - if you don't have time then just go to the simple form of my question down there...
Here is what I know about the topic so far:
1) I need to use a macro defined as __declspec(ddlexport) and __declspec(ddlimport) before class name to export all the class methods and variables
2) I need to use extern "C" somewhere but I am not sure exactly where
3) There are many ways to do this (pass class as parameter to methods that accept it c approch/ export class / use interface)
Here is why and how I am lost:
1) Most of tutorials are for exporting methods, which I suspect is very easy compared to classes (in C# you use [Dllimport, name of DLL] then you invoke each method)
2) Do i need to use extern "C" with classes or not?
3) If I used a factory method with an interface do i need distribute the .h file containing the interface?
Here is what i want to do:
1) create a C++ DLL with a class in it and to export that class to be used in .NET or C++ (I want to protect my code, since I saw how easily you can reverse managed code using the stored IL.)
2) I want to have 2 DLLs, one C++ native DLL, and the other one will be the wrapper DLL, so that if someone wants to use my class in C++ he can use the native DLL directly and if he wants to use it in C#/VB.net he can use the C++/CLI wrapper DLL...
3) no libs, no header files, no def files,...etc..... only pure DLLs (2 files will be released)
Simple form
Let's say I want to instantiate an object in C# from this C++ class
Class Human
{
private:
int Pee_Meter;
public:
Void Do_Pee()
{
//stuff here
};
};
What do I need to do, basic stuff only? With the least possible number of files and maximum code protection, no releasing of header files or anything, only using DLLs and probably a txt file that mention methods names and stuff to use in DLL.
In other words, are these steps correct?
1) In VS2012 create new Win32 project, then select DLL as type of project
2) define macro __declspec(ddlexport) / __declspec(ddlimport) and use it before class name (should I use extern "C" with classes? Probably not...)
3) Compile DLL
4) Create a CLR project in VS2012 to use C++/CLI
5) Link the native DLL (I don't know how?? PInvoke entire class???????)
6) Define wrapper class (which I am still learning, but I think you create a method in CLI for every method in native class)
7) Compile the CLI DLL
Should I say that I have Deitel and Ditel C // Deitel and Ditel C++ // C++ programming by D. S. Malik and non of these three books mention anything about making DLLs which I think is kind of stupid.
Finally, thank you for every second you wasted in helping me, I really appreciate every help you provide even if you directed me toward a tutorial that I have read before... I might have missed something in it :)
Having done this a bunch of times, the easiest way to do this is to write a C++/CLI wrapper to your existing classes. The reason being that P/Invoke works best on calls that are strictly C functions and not methods in a C++ class. In your example, how would you call operator new for the class that you specify?
If you can write this as a C++/CLI dll, then what you get is something that looks like this:
public ref class CliHuman {
public:
CliHuman() : _human(new Human()) { }
~CliHuman() { delete _human; }
protected:
!CliHuman() { delete _human; }
public:
void DoPee() { _human->Do_Pee(); }
private:
Human *_human;
};
Now, you might not have the freedom to do this. In this case, your best bet is to think about what it would take to expose a C API of your C++ object. For example:
extern "C" {
void *HumanCreate() { return (void *)new Human(); }
void HumanDestroy(void *p) { Human *h = (Human *)h; delete h; }
void HumanDoPee(void *p) { Human *h = (Human *)h; h->Pee(); }
};
You can P/Invoke into these wrappers very easily.
From an engineering standpoint, you would never want to do this ever since calling .NET code could pass in any arbitrary IntPtr. In my code, I like to do something like this:
#define kHumanMagic 0xbeefbeef;
typedef struct {
int magic;
Human *human;
} t_human;
static void *AllocateHuman()
{
t_human *h = (t_human *)malloc(sizeof(t_human));
if (!h) return 0;
h->magic = kHumanMagic;
h->human = new Human();
return h;
}
static void FreeHuman(void *p) /* p has been verified */
{
if (!p) return;
t_human *h = (t_human)p;
delete h->human;
h->human = 0;
h->magic = 0;
free(h);
}
static Human *HumanFromPtr(void *p)
{
if (!p) return 0;
t_human *h = (t_human *)p;
if (h->magic != kHumanMagic) return 0;
return h->human;
}
void *HumanCreate() { return AllocateHuman(); }
void HumanDestroy(void *p)
{
Human *h = HumanFromPtr(p);
if (h) {
FreeHuman(p);
}
else { /* error handling */ }
}
void HumanPee(void *p)
{
Human *h = HumanFromPtr(p);
if (h) h->Do_Pee();
else { /* error handling */ }
}
What you can see that I've done is create a light wrapper on top of the class that lets me verify that what comes in is more likely to be a correct pointer to what we want. The safety is likely not for your clients but for you - if you have to wrap a ton of classes, this will be more likely to catch errors in your code where you use one wrapper in place of another.
In my code base, we have found it especially useful to have a structure where we build a static library with the low-level code and the C-ish API on top of it then link that into a C++/CLI project that calls it (although I suppose to could P/Invoke into it from C# as well) instead of having the C++/CLI directly wrap the C++. The reason is that (to our surprise), all the low-level code which was using STL, was having the STL implementations done in CLI rather than in x86 or x64. This meant that supposedly low-level code that was iterating over STL collections would do something like 4n CLI transitions. By isolating the code, we worked around that quite well.
I think you'd be better off making a plain C interface to your C++ code. C++ linking is really only good for other C++ programs, due to name mangling. C functions, however, can be used in many languages without any problem - python, C#, haskell, etc.
Let's suppose, however, you want to have some C++ classes accessible from your C interface. The way I like to do this is:
in my C++ dll have a global object registry. basically a map from int to object.
whenever I create an object, it gets a new registry ID.
whenever I call a function that uses the object, I pass in the ID.
so something like this:
int CreateNiftyInstance()
{
int i = global_store.get_id();
Nifty *n = new Nifty();
global_store.save_obj(i, n);
return i;
}
void DoSomethingNifty(int id, const char *aCData)
{
// lame dynamic cast. Making it type safe is possible with dedicated stores for
// each type of object.
Nifty *n = dynamic_cast<Nifty*>(global_store.get_obj(i));
if n
{
n->DoSomething(aCData);
}
}
ah i think I found what I was looking for after reading this [http://www.codeproject.com/Articles/9405/Using-classes-exported-from-a-DLL-using-LoadLibrar]
correct me if wrong
first I need to either export the native class or mark a factory method as extern "C"
then in the CLR project I use the factory method or use Loadlibrary + malloc commands to get an instance of the class if I did not go with the factory method approach
create the wrapper class as plinth had told me to do (many thanx to him). and use the instance from the previous step to call methods in my class
include both dlls in the release and instructe developers to reference the CLR dll only.
if that is the way then iam very greatfull for all of you guys
going to start working on it soon...
Yours...

Wrapping C++ for use in C#

Ok, basically there is a large C++ project (Recast) that I want to wrap so that I can use it in my C# project.
I've been trying to do this for a while now, and this is what I have so far. I'm using C++/CLI to wrap the classes that I need so that I can use them in C#.
However, there are a ton of structs and enums that I will also need in my C# project. So how do I wrap these?
The basic method I'm using right now is adding dllexport calls to native c++ code, compiling to a dll/lib, adding this lib to my C++/CLI project and importing the c++ headers, then compiling the CLI project into a dll, finally adding this dll as a reference to my C# project. I appreciate any help.
Here is some code..I need manageable way of doing this since the C++ project is so large.
//**Native unmanaged C++ code
//**Recast.h
enum rcTimerLabel
{
A,
B,
C
};
extern "C" {
class __declspec(dllexport) rcContext
{
public:
inline rcContect(bool state);
virtual ~rcContect() {}
inline void resetLog() { if(m_logEnabled) doResetLog(); }
protected:
bool m_logEnabled;
}
struct rcConfig
{
int width;
int height;
}
} // end of extern
// **Managed CLI code
// **MyWrappers.h
#include "Recast.h"
namespace Wrappers
{
public ref class MyWrapper
{
private:
rcContect* _NativeClass;
public:
MyWrapper(bool state);
~MyWrapper();
void resetLog();
void enableLog(bool state) {_NativeClass->enableLog(state); }
};
}
//**MyWrapper.cpp
#include "MyWrappers.h"
namespace Wrappers
{
MyWrapper::MyWrapper(bool state)
{
_NativeClass = new rcContext(state);
}
MyWrapper::~MyWrapper()
{
delete _NativeClass;
}
void MyWrapper::resetLog()
{
_NativeClass->resetLog();
}
}
// **C# code
// **Program.cs
namespace recast_cs_test
{
public class Program
{
static void Main()
{
MyWrapper myWrapperTest = new MyWrapper(true);
myWrapperTest.resetLog();
myWrapperTest.enableLog(true);
}
}
}
As a rule, the C/C++ structs are used for communicating with the native code, while you create CLI classes for communicating with the .NET code. C structs are "dumb" in that they can only store data. .NET programmers, on the other hand, expect their data-structures to be "smart". For example:
If I change the "height" parameter in a struct, I know that the height of the object won't actually change until I pass that struct to an update function. However, in C#, the common idiom is that values are represented as Properties, and updating the property will immediately make those changes "live".
That way I can do things like: myshape.dimensions.height = 15 and just expect it to "work".
To a certain extent, the structures you expose to the .NET developer (as classes) actually ARE the API, with the behaviors being mapped to properties and methods on those classes. While in C, the structures are simply used as variables passed to and from the functions that do the work. In other words, .NET is usually an object-oriented paradigm, while C is not. And a lot of C++ code is actually C with a few fancy bits thrown in for spice.
If you're writing translation layer between C and .NET, then a big part of your job is to devise the objects that will make up your new API and provide the translation to your underlying functionality. The structs in the C code aren't necessarily part of your new object hierarchy; they're just part of the C API.
edit to add:
Also to Consider
Also, you may want to re-consider your choice to use C++/CLI and consider C# and p/invoke instead. For various reasons, I once wrote a wrapper for OpenSSL using C++/CLI, and while it was impressive how easy it was to build and how seamless it worked, there were a few annoyances. Specifically, the bindings were tight, so every time the the parent project (OpenSSL) revved their library, I had to re-compile my wrapper to match. Also, my wrapper was forever tied to a specific architecture (either 64-bit or 32-bit) which also had to match the build architecture of the underlying library. You still get architecture issues with p/invoke, but they're a bit easier to handle. Also, C++/CLI doesn't play well with introspection tools like Reflector. And finally, the library you build isn't portable to Mono. I didn't think that would end up being an issue. But in the end, I had to start over from scratch and re-do the entire project in C# using p/invoke instead.
On the one hand, I'm glad I did the C++/CLI project because I learned a lot about working with managed and unmanaged code and memory all in one project. But on the other hand, it sure was a lot of time I could have spent on other things.
I would look at creating a COM server using ATL. It won't be a simple port, though. You'll have to create COM compatible interfaces that expose the functionality of the library you're trying to wrap. In the end, you will have more control and a fully supported COM Interop interface.
If you are prepared to use P/Invoke, the SWIG software could maybe help you out: http://www.swig.org/

How to use C++ class instance in C#

I have a DLL that contains a class that inherits from another abstract C++ class defined as following:
class PersonInterface
{
public:
virtual int __stdcall GetName() = 0;
};
The DLL exports a function that can be used in C# as following (following method is part of static class PersonManager):
[DllImport( "person.dll", CallingConvention = CallingConvention.Cdecl )]
public static extern bool GetPerson( out PersonInterface person );
where PersonInterface is defined in C# class as following:
[StructLayout( LayoutKind.Sequential )]
public class PersonInterface
{
}
I can successfully retrieve the C++ class instance like this:
PersonInterface person;
bool retrieved = PersonManager.GetPerson( out person );
However, the retrieved object is not of any use until GetName method can be called.
What else needs to be done in order to be able to be able to invoke GetName method on retrieved person object?
string name = person.GetName();
Compile your C++ DLL using /clr compiler option.
Write up a managed class using public ref class syntax, and have pointer to your native class in this class. Expose all methods from this managed class and forward all calls to your native class.
Import this DLL as assembly in your c# project and use this class as you would use any other .NET class.
You need to compile only few source files using /clr flag, not all. Let all native source files be compiled as native. Your DLL will be linked to VC runtime DLL as well as .NET runtime DLL.
There is lot to managed class, /clr, Interoperability/Marshalling, but at least get started.
You may choose your favorite articles from here
You`ll have to write a wrapper in C++ (it may be managed C++), where you call you C++ clasess and expose either flat dll functions, which can be called from .Net, or .Net classes (if you used managed C++), that will be accessible from .Net.

Class Library in C#

I tried to create a class library that is being used in a winforms application in C#.
In my application I have input from a textbox and through a button click I'm instantiating
my event with one parameter (from the textbox). I tried to create a constructor with
this one parameter - but to no avail. It seems if I just add a class to be existing
project I can do this but not when referencing a class library.
Just wanted to find a way to use a one parameter constructor within a class library
if possible. Please help. (this may not work logically because when I reference the
class library - I am actually going outside the original assembly - but maybe....)
If your new class library is in a separate C# project you need to set a reference to that project from your WinForms app before you can use the class.
Of course I'm trying to read between the lines of your original post. It sounds like you know how to make it work, just not when the class is defined in a seperate project. If I've misunderstood, please give more info.
Not enough site experience to upvote or comment myself yet, but DRapp's answer fixed my problem. Since the original question is a bit vague I thought I'd detail what I was seeing a bit more:
I am writing a metro application in C++ which references a class library created in C#. Creating objects exported from the C# module was working fine, unless their constructors had parameters.
// C# file exported to .winmd class library for use in metro app
namespace A
{
public sealed class B
{
public B(bool bTest)
{}
// Other methods/members...
}
}
// C++ metro app referencing .winmd created from C# above
...
A::B^ spB = ref new A::B(bTest); // Throws an exception
Attempting to create an object of type B from the C# module in C++ would throw an exception, with a somewhat cryptic "WinRT transform error" show in the output log.
To fix this, I was able to do what DRapp suggested and add a default constructor to B:
// C# file exported to .winmd class library for use in metro app
namespace A
{
public sealed class B
{
public B()
{}
public B(bool bTest)
{}
// Other methods/members...
}
}
No more exception. :)
it sounds like you don't have two constructors... (overloaded) for your class such as
public class YourClass
{
public YourClass()
{
}
public YourClass(String OneParameter) // this OVERLOADS the default No parameter one
{
DoWhatever with your OneParameter...
}
}

Categories

Resources