I have a solution with 3 projects. A C# WinForms project which depends on second project which is a C++ DLL. The C++ DLL depends on the third project which is a static library. The static library is C code with C++ classes. The DLL acts as an interop between the C code and C# code.
I need to set the variables used by the static library through C# structure.
I do not have experience in C++/CLI (I have started reading. Examples found on the web do not make sense to me as of now)
So far, I have created a structure in C#. I created a initialized unmanaged memory to hold this struct:
IntPtr ptData = Marshal.AllocHGlobal(Marshal.SizeOf(objMyClass.data));//data is the structure I am initializing in the constructor of MyClass
Marshal.StructureToPtr(objPythonInterop.data, ptData, false);
objCPPClass.UpdateData(ptData);//objCPPClass is object to class in DLL. libClass is the object of class in static library
This is my structure in C#:
[StructLayout(LayoutKind.Sequential)]
public struct Data
{
members here..
}
In the DLL, this is the UpdateData function:
Header:
void UpdateData(IntPtr ptrData);
Source:
void CPPClass::UpdateData(IntPtr ptrData)
{
m_lib->UpdateDataInLib(ptrData);// m_lib is object to class in static library
}
UpdateDataInLib is a function in the Class in Static library. How do I use the ptrData in this function and update the variables? I have a structure in the static library similar to the structure defined in my C# code. How do I cast the ptr to this structure and access the members?
I have a structure in my C++ static library which contains equivalent members of the structure in C#:
extern "C" __declspec(dllexport) typedef struct Data
{
members here..
}Data, *pData;
I need help.
There's a simpler approach. You don't need dynamic memory allocation if your DLL doesn't access the structure anymore after the call. Just put the structure on the stack (you still need fixed nevertheless):
var data = new objMyClass.data
{
field1 = value1, // etc
};
unsafe
{
fixed (objMyClass.data* ptr = &data)
{
objCPPClass.UpdateData(new IntPtr(ptr));
}
}
If the structure is long-lived then keep your code as-is but don't forget to free the allocated memory.
Then, on the C++ side, you could just cast:
void CPPClass::UpdateData(IntPtr ptrData)
{
m_lib->UpdateDataInLib(static_cast<pData>(ptrData.ToPointer()));
}
But as I don't know the signature of UpdateDataInLib I'm not sure about this approach.
Also, you can get rid of the IntPtr intermediate step, and just use a pointer.
Related
I can call C++ wrapper class from C# via
[DllImport("SomeDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void M();
Where in the C++ code I have
extern "C" { __declspec(dllexport) BSTR GroupTerm(); }
void M() { /* Do Stuff */ }
This works great, however for a number of reasons, I want to include the method M in a class
class SomeClass {
public:
void M();
}
I have tried doing
class SomeClass {
public:
void __declspec(dllexport) M();
}
where
void __declspec(dllexport) SomeClass::M() { /* Do Stuff */ }
But the C# code (using the C# code for import declared above) cannot find the entry point and throws an exception. My question is then, how can I export this method M() [which is a public member of SomeClass for use with interop/pinvoke from C#?
Thanks for your time.
Well there is a few ways, all with different merrits.
One of the more simple is to make a C-wrapper for your C++ class (i'm too lazy to put in the decorations, you should do that yourself).
class SomeClass {
public:
void M();
};
void* MakeSomeClass() {return new SomeClass();}
void DestroySomeClassHandle(void* handle) { delete (SomeClass*)handle;}
void M(void* handle) { ((SomeClass*)handle)->M();}
Then you import the C functions as you normally would.
The upside to this is you don't have to do anything you aren't currently familiar with. Many more things (Matlab, Python, ect) have things similar to PInvoke, so this makes your code much more cross-language usable.
The downside is this is super error prone, and you throw away alot of your type safety.
The better way (imho) is to make a C++/CLI wrapper for the class
public ref class ManageSomeClass
{
public:
ManageSomeClass() {myclass_ = new SomeClass();}
!ManageSomeClass() { if (myclass) {delete myclass; myclass_ = NULL;} }
~ManageSomeClass() { this->!ManageSomeClass(); }
void M() { myclass_->M();}
private:
SomeClass* myclass_;
};
I used SomeClass as a pointer to show the destructor-finalizer, but it doesn't need to be a pointer. It could be a full instance. The big thing is that this will be compiled into a .NET class (in a dll) and you can import it into your C# code. Then the call is:
//c# code
ManageSomeClass msc = new ManageSomeClass();
msc.M();
Upside is the flexibility to go from managed to unmanaged like that. The downside is that you are suddenly maintaining another interface. If you have inheritence/polymorphism, your wrappers have to mirror that structure. This is also a nightmare to maintain.
Edit: Another downside is you have to learn C++/CLI, which is (kindof) and extension of C++ and also (kindof) a completely different language.
The final way is through COM interfaces. http://msdn.microsoft.com/en-us/library/aa645736%28v=vs.71%29.aspx. You can use the same COM import calls you use in C++ in C# (with some minor differences) to instantiate and call COM classes. But you need to learn COM (which I've never done) and then implement your class in a COM complaint way. But then you have a COM interface, which can be imported all over Windows.
Assuming the method is static you have a couple of choices:
Use a tool like Dependency Walker to find out the name under which the function is imported. Use the EntryPoint parameter of DllImport to locate it.
Export the function with a .def file. Then you have total control over the exported name.
Wrap the method in a non-member function and export that.
Frankly, option 3 is the one I would select.
When you get around to member functions you'll need to export functions that accept an instance pointer as their first parameter. And you'll likely have to export functions that instantiate objects.
That said, and responding to your comments, other likely better solutions to your problem are:
Early bound COM, or
A C++/CLI wrapper.
Another method (apart from what #MadScienceDreams and #DavidHeffernan said) is to make your C++ code into a Windows Runtime DLL and then it can be used in your C# code. See here for the details and sample: Creating Windows Runtime Components in C++
Excerpt from the link:
article shows how to use C++ to create a Windows Runtime component,
which is a DLL that's callable from a Windows Store app that's built
by using JavaScript—or C#, Visual Basic, or C++
...
In general, when you code your C++ component, use the regular C++
library and built-in types, except at the abstract binary interface
(ABI) boundary where you are passing data to and from code in another
.winmd package. There, use Windows Runtime types and the special
syntax that Visual C++ supports for creating and manipulating those
types. In addition, in your Visual C++ code, use types such as
delegate and event to implement events that can be fired from your
component and handled in JavaScript, Visual Basic, or C#.
Here is the sample code for "Creating Windows Runtime Components in C++".
Could somebody tell me what the difference between CLR and CLI is in it's basic functionallity but most important would be which one of them is better?
All I got so far is that using the ICLRRuntimeHost Interface does not allow me to return anything else than an int and the only allowed parameter is a LPCWSTR (see ExecuteInDefaultAppDomain)
At this point I am wondering if one could/would allocate memory e.g. for a struct in his C program, give a pointer as a LPCWSTR string to ExecuteInDefaultAppDomain and translates this pointer back into that struct on the other side to work on that struct. I don't get it how one can work with the limitation of this signator for each function: int fncname(string param);
I took a look at this tutorial but I don't get it how calling C++/CLI from a C program works and how I could return complex objects or anything more complex than an int.
And could somebody please show me HOW I can use CLI within C? I can't seem to find some lines of code that would show how that would work.
You can pass and return complex data in CLI. CLI is an intermediate layer. when you pass data from a managed code(.NET) to native code (c,c++) you need a intermediate layer which will take responsibility of managed to native object and vice verse conversation because managed objects are managed by Garbage collector and native objects are managed by programmer (need to delete when created).
In C++/CLI there are two type of class. 1) Manged class 2) Native class. A managed class is defined as :
public ref class ManagedClass
{
NativeObject* native;
ManagedObject^ mObject;
}
This can contain managed and native object. So in this class you create a managed/native class object which is replica of native/managed object (in terms of containing data and method). The basic data in any object is either another object or basic primitive data which can be easily converted. You have to take care of objects only.
Suppose you want to execute C++ method form .NET. Your c++ code has an object called NativeClass and your c++ method return this native object. You can't pass this object directly to .NET layer. So you will store that object instance in variable native of above class ManagedClass. Note that you can access native as well as managed object in CLI layer. Now you create a manged object class in CLI which will be exact replica of native class in term of containing data. Now you copy all date from Native object to managed object and assign that managed object instance to variable mObject. Now you can pass this variable mObject to .NET layer because this is Manged object.
Similar approach can be used when you pass Managed object to Native method.
You can go through this PDF to know more about C++/CLI.
http://asawicki.info/Download/Productions/Publications/CPP_CLI_tutorial.pdf
UPDATE:
I will recommend you to first go through the PDF. Below is a simple example how this conversion happens. NativeObject is C++ object (You can also have C struct instaed of Class) and ManagedObject is C# object and CLIInterface is used to provide interface.
public ref class CLIInterface
{
private:
NativeObject* native;
ManagedObject^ mObject;
public:
CLIInterface(NativeObject* nativeObj){
native = nativeObj;
mObject = gcnew ManagedObject(nativeObj);
}
string getNativeMessage();
int getNaiveID();
String^ getManagedMessage();
int getmanagedID();
}
Native class:(C++ Object or C struct and can be used in CLI)
public class NativeObject
{
private:
int id;
string msg;
public:
string getMessage(){return msg;}
int getID(){return id;}
}
Managed class: (C# object and you can use it in CLI)
public ref class ManagedObject
{
private:
NativeObject* native;
public:
ManagedObject(NativeObject* obj){
native = obj;
}
String^ getMessage(){
convertNativeToCLI(native->getMessage()); //you can use marshaling to implement convertNativeToCLI method.
}
int getID(){
return native->getID();
}
}
You can use Managed class object and CLIInterface from C# code and you can use Native Object in C++ code. I hope this will help. You can also go to Microsoft's C++/CLI documentation.
I am new to C# but have worked extensively with C++. I have a C++ function that needs to be called from C#. After reading some answers from SO and some googling, I conclude that I need to make a pure C interface to the function. I have done this, but am still confused about how to call it from C#.
The function in C++ looks like this:
int processImages(
std::string& inputFilePath, // An input file
const std::vector<std::string>& inputListOfDirs, // Input list of dirs
std::vector<InternalStruct>& vecInternalStruct, // Input/Output struct
std::vector<std::vector< int > >& OutputIntsForEachFile,
std::vector< std::vector<SmallStruct> >& vecVecSmallStruct, // Output
int verboseLevel
);
The same function, converted in C, looks like this:
int processImagesC(
char* p_inputFilePath, // An input file
char** p_inputListOfDirs, // Input list of dirs
size_t* p_numInputDirs, // Indicating number of elements
InternalStruct* p_vecInternalStruct, // Input/Output struct
size_t* p_numInternalStructs,
int** p_OutputIntsForEachFile, // a 2d array each row ending with -1
size_t* p_numOutputIntsForEachFile //one number indicating its number of rows
SmallStruct** p_vecVecSmallStruct, // Output
size_t* p_numInVecSmallStruct,
int verboseLevel
);
This is based on this advice.
Now I need to call this from C#, which is where the confusion is. I have tried my best to convert the structures.
The C# code looks like this:
[DllImport(
#"C:\path\to\cppdll.dll", CallingConvention=CallingConvention.Cdecl,
EntryPoint="processImagesC", SetLastError=true)]
[return: MarshalAs(UnmanagedType.I4)]
unsafe public static extern int processImagesC(
String inputFilePath,
String[] inputListOfDirs,
ref uint numInputListOfDirs,
// Should I use ref InternalStruct * vecInternalStruct?
ref InternalStruct[] vecInternalStruct,
ref uint numInternalStruct,
// Or ref int[] or ref int[][] or int[][]?
ref int[][] OutputIntsForEachFile,
ref uint numOutputIntsForEachFile,
// again, ref ..[], [][], or ref [][]?
ref SmallStruct[][] vecVecSmallStruct,
int verboseLevel
);
There are memory allocations for all the output variables (pointers) done within the C/C++ code. This likely means we need to declare the code as unsafe, correct?
How do we handle memory deallocation? Should I write another API (function) that does the deallocation of objects/arrays allocated by C/C++?
The C++ code needs to be standard compliant and platform independent, so I cannot insert any windows-specific things in it.
I hope someone could make sense of this and provide an answer or at least point me in the right direction.
Since there seems to be some interest in using It Just Works (IJW) with C++/CLI, I'll post some info about that, further google searches and research will need to be done to figure it all. C++/CLI can be enabled with a single compiler flag (/CLI, enabled through Property Page->General->Common Language Runtime Support). C++/cli is NOT c++, but rather just another managed language. C++/CLI classes can be compiled into dll's and called directly from other .NET projects (C#, VB.NET, ect). However, unlike the other .NET languages it can directly interact with C++ code.
This is an ok start to learning C++/CLI. The big thing to learn is the decorations that tell you the class is managed (.NET class) and not Vanila C++. The "ref" keyword decalres the definition as a .NET definition:
public ref class Foo{ public: void bar();};//Managed class, visible to C#
public ref struct Foo{};//Managed struct, visible to C#
All reference classes are referred to with Handles rather than pointers or references. A handle is denoted by the ^ operator. To make a new handle, you use gcnew, and to access functions/members of the handle, use the -> operator.
//in main
Foo^ a = gcnew Foo();
a->bar();
You often have to move structures common from C# to native types and back again. (such as managed Array^ or String^ to void* or std::string). This process is called Marshaling. This handy table is pretty useful for figuring that out.
A common task is to create a wrapper for a native class, done like this:
//Foo.h
#include <string>
namespace nativeFoo
{
class Foo
{
private:
std::string fooHeader;
public:
Foo() {fooHeader = "asdf";}
std::string Bar(std::string& b) {return fooHeader+b;}
};
}
//ManagedFoo.h
#include "foo.h"
namespace managedFoo
{
public ref class Foo
{
private:
nativeFoo::Foo* _ptr;
public:
Foo(){_ptr = new nativeFoo::Foo();}
~Foo(){!Foo();}
!Foo(){if (_ptr){delete ptr;ptr = NULL;}}
String^ bar(String^ b)
{
return marshal_as<String^>(_ptr->bar(marshal_as<std::string>(b)));
}
};
}
Warning: I am totally missing a bunch of #include and #using statements, this is just to give a general gist of how to use this.
Begin from this:
How to pass structure as pointer in C dll from C#
And something about marshalling in this:
Deep copying an array c# without serialization
Note that Marshal.Copy also overloads for arrays use. With marshalling you can get rid of ref excepting that you do want to. Just write C/C++ in their way.
And following is a little bit complicated:
Physical disk size not correct (IoCtlDiskGetDriveGeometry)
The 2 ways I've often seen this handled is to either have a 'FreeResource' style API, or specify in the function the size of output buffers.
Method 1
C++
void GetName(char ** _str)
{
if (!_str)
return; // error
*_str = new char[20];
strcpy(*str, "my name");
}
void FreeString(char * _str)
{
delete str;
}
Client (any language)
char * name;
GetName(&name);
...
FreeString(name);
Method 2
C++
void GetName(char * _str, size_t _len)
{
if (_len < 20)
return; // error
strcpy(str, "my name");
}
Client (any language)
char * name = new char[20];
GetName(name, 20);
...
If you are willing to use third party tool, there is a tool named C#/.NET PInvoke Interop SDK may be helpful to you. But you can do it yourself as well. For simple classes with a few methods, you can write your own code in managed C# code.
The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.
Here is an example.
public class SampleClass : IDisposable
{
[DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void SampleClassConstructor(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject, int x);
IntPtr ptr;
public SampleClass(int sizeOfYourCppClass)
{
this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
SampleClassConstructor(this.ptr);
}
public void DoSomething()
{
DoSomething(this.ptr);
}
public void DoSomethingElse(int x)
{
DoSomethingElse(this.ptr, x);
}
public void Dispose()
{
Marshal.FreeHGlobal(this.ptr);
}
}
For the detail, please see the below link,
C#/.NET PInvoke Interop SDK
The tool, xInterop NGen++ 2.0 has been released. Please check it out if you are interested in creating C# wrapper for native C++ DLL.
(I am the author of the SDK tool)
I need to use a DLL coded in C++ in a C# application, there is a method in the DLL with receives a object declared in the C++ and I don't know how to parse a equivalent object maded in C# to the function of the DLL
Can someone help me?
You will need to use the System.Runtime.InteropServices namespace with Platform Invoke if the c++ code is not managed or COM. You will need to define the structure in your C# application and pass an object of whatever type your structure is to the method you are using Platform Invoke on. To tell you anymore, I need to see some header files.
Here is a sample :
c++ header:
struct MyStruct
{
int size;
char* data;
}
bool MethodToInvoke(MyStruct* obj);
c# declarations:
struct MyStruct
{
int size;
string data;
}
[DllImport("YourDllHere.dll")]
static extern bool MethodToInvoke(ref MyStruct obj);
Of course, it could get much more complicated but that is the general idea.
It can and may get really nasty when you have to worry about calling conventions and marshaling arrays. Regardless the world needs to see some code from you.
I am working on an enterprise application development. the entire application is developed in c++, except the UI, which is developed in c#, now its time to hookup the UI with c++ code. After detailed study i choose PInvoke in order to do so.
All is successful, the only case where i stuck is that how can i pass collection to C++ code.
e.g:
C# Side Code
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
C++ Side Code
std::vector<std::string> vStr;
Now how do i pass lst to native C++ code
As mzabsky mentioned, you cannot marshal these types. You can, however, marshal an array:
The theoretical C++ export:
extern "C" __declspec(dllexport) void __stdcall Foo(wchar_t const* const* values, int length)
{
// Check argument validity...
// If you really need a vector
std::vector<std::wstring> vStr(values, values + length);
//...
}
The P/Invoke signature:
[DllImport("foo.dll")]
static extern void Foo([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)] string[] values, int length);
The call from C#:
Foo(lst.ToArray(), lst.Count);
Note that I'm using std::wstring here; you could instead use char instead of wchar_t, LPStr instead of LPWStr, and std::string instead of std::wstring.
Note that this will allocate an array from the list and then the vector will copy the array's contents. If the original list is small in size, this should be of negligible concern.
Edit: fixing markup (< and >).
You can't do this, only C types can be marshalled. You will have to write a C++/CLI wrapper (or a C wrapper around the C++ vector).
See this answer.
Yes. You can. Actually, not just std::string, std::wstring, any standard C++ class or your own classes can be marshaled or instantiated and called from C#/.NET.
Wrapping a std::vector<any_type> in C# is indeed possible with just regular P/Invoke Interop, it is complicated though. even a std::map of any type can be done in C#/.NET.
The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.
Here is an example.
public class SampleClass : IDisposable
{
[DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void SampleClassConstructor(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject, int x);
IntPtr ptr;
public SampleClass(int sizeOfYourCppClass)
{
this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
SampleClassConstructor(this.ptr);
}
public void DoSomething()
{
DoSomething(this.ptr);
}
public void DoSomethingElse(int x)
{
DoSomethingElse(this.ptr, x);
}
public void Dispose()
{
Marshal.FreeHGlobal(this.ptr);
}
}
For the detail, please see the below link,
C#/.NET PInvoke Interop SDK
(I am the author of the SDK tool)