Using a C++ function template from CLI wrapper - c#

I'm building a C++/CLI DLL to be able to communicate a plain C++ DLL with a C# application. The plain C++ DLL is third party provided and I have no way to modify it.
That plain C++ DLL contains some member function templates, in the way:
plain C++ DLL header file:
class pureCPP
{
template<typename T>
void usefulFunctionA(T &b, T const &a)
{
/* Implementation of the function */
}
}
So my idea would be to reflect that in the CLI DLL header file:
CLI DLL header file:
public ref class CLI_DLL
{
template<typename T>
void usefulFunctionB(T &b, T const &a)
{
pureCppPtr->usefulFunctionA(b, a);
}
PureCPP *pureCppPtr;
}
And then in the C# executable for example simply call:
CLI_DLL cliDLL = new CLI_DLL;
double a, b;
cliDLL.usefulFunctionB<double>(a, b);
Is this doable? Or am I forced to simply instantiate overloads for every possible type of the function template?
I've read C# has something called generics, could I use that technique to achieve something like this? So far, every article I've found refers either to class templates (not just methods within them) or suggests to do explicit instantiation in the CLI of the desired types, which is what I'd like to avoid if possible (suppose each function can be used by 1000 different types...I guess it wouldn't be so nice to replicate the 1000 different instantiations).
I'm a completely newbie to C#, but AFAIU, passing arguments (in this case, a type) from a generic function to a template wouldn't be doable since the former are resolved at runtime while the latter is done at compile time, in which case I'd be forced to change the previous implementation to something like this:
CLI DLL header file:
public ref class CLI_DLL
{
/* Only define the template here */
template<typename T>
void usefulFunctionB(T &b, T const &a);
PureCPP *pureCppPtr;
}
CLI DLL source file:
/* Explicitly instantiate the template in the source file */
template<>CLI_DLL::usefulFunctionB<double>(double &A, double const &B)
{
pureCppPtr->usefulFunctionA<double>(b, a);
}
on so on for every type I need. The other way (template to generic) seems to be possible though, right?
(BTW, and as a side question, is it really necessary to explicit the type being called, "double" in this case? I've never really understood why in some cases, Visual Studio is not able to automatically deduct types from templates, as CLang or GCC are).
Which is what I'd really, REALLY liked to avoid, and instead, I'd love to be able to do something like the first code I exposed.
Thanks a lot in advance.

Related

Managed C++ Wrapper for C Code - Identical function names issues

I have been tasked with creating a Wrapper for a C-library to be used in C#. I have no control over the C-library's source code and I only have access to its header file and to the static library file (.lib).
I have followed several tutorials and got this working when creating an unmanaged C++ class which is wrapped using CLI/C++ and used in C#. No problem. The problem I am facing know though, is as C does not use namespaces, I have trouble figuring out how to tell the compiler when I want to call the function from the .lib file itself, rather than my identically named wrapper function. If it helps understanding, my header file only consists of function definitions, typedefs (structs, enums), but no classes (not even sure if C headers usually do?).
What I have done:
Created a VS C++ CLR Class Library (.NET Framework) project
Linked my .lib file to all configurations in linker->inputs as an additional dependency.
Created two files: Wrapper.h and Wrapper.cpp.
#included the header file corresponding to my .lib in the Wrapper.h file
This is where I get a bit confused, mostly due to the tutorials all covering how to link a C++ library rather than a C library. The difference there being the lack of namespace in C, and (in my case) the lack of class.
Uncertainties:
I do not know if I need a ref class Analytics{} in my Wrapper.h or not. I assume I do if I want to use all the functions statically, but as there is no corresponding class in the C library, can I just name this whatever I want?
In order to properly link the C library in my header file (Wrapper.h), I need to use the same function definition as in the original header file. Do I repeat the use of "extern" and such keywords? Can I freely add static and accessibility modifiers?
At this point I want to "implement" the function in the Wrapper.cpp file. Here my problem about identical function names comes in. The function I want to implement has the same name in the original header file as it does in the Wrapper header file (obviously, as it would not work otherwise, right?). The wrapper header file contains a namespace and a class (for now class name is Analytics) so I can declare the function as Analytics::void SanSetApplicationContext(){...}, but as the original C library header file does not contain classes or namespaces, there is no way for me to call that function and distinguishing between them. The C++ compiler always prefers the local definition and I am stuck with a function calling itself for all eternity. I hope you understand my point.
I am probably doing something wrong and/or misunderstanding something, but how would you guys suggest I approach this issue? I will append my files contents below. In the files I have so far only tried implementing a single function. Code should be fixed and hopefully working
Wrapper.h
#pragma once
using namespace System;
namespace Wrapper {
public ref class Analytics
{
public:
static void SanSetApplicationContext(String^ ctx);
};
}
Wrapper.cpp
#include "pch.h"
#include "Wrapper.h"
#include "../SWA_lib/Analytics.h"
namespace Wrapper {
void Analytics::SanSetApplicationContext(String^ ctx) {
//Convert String^ to const char*
msclr::interop::marshal_context mCtx;
const char* convertedStr = mCtx.marshal_as<const char*>(ctx);
::SanSetApplicationContext(convertedStr);
}
}
Analytics.h
...
extern void SanSetApplicationContext(const char *ctx);
...
Update
Updated the code to reflect my changes made based on your comments. Thanks!
Update 2
#Bodo asked me to explain another issue of mine, which is how I would handle wrapping functions that return opaque handles. The example used is the following: typedef struct SanEvent_s *SanEvent; which is found in my C header file. So basically, this library provides an API. The API execution always starts with a call to an Initialize(); function, and ends with a call to the Terminate(); function. I have no previous experience of using this API, but from the documentation, I assume that all objects, references and what not are freed/destroyed when Terminate() is called, as none of their examples show destroying objects.
Now, creating a SanEvent is done like this (according to documentation):
SanEvent event;
event = SanNewEvent("The Main Event");
This opaque handle is considered protected on the C# side, so there does not seem to be a way for me of returning it all the way there. My idea is to keep the events in some kind of Collection, in the C++/CLI wrapper where the type can be used, and only return the index of the Event to C# (The index the even would have in a List or something). I am not sure this is a good idea, but this is as far as I have come with my plan. Something that represents a SanEvent needs to be returned to C# as I need to be able to reference the event in the future, in order to add additional information to the event via other functions. This idea would of course need tailored "helper functions" on the C++ side which mediate between C# and C. I am sorry if the information is vague, but I don't really have a lot to go on myself as of now.
Adding "::" to the beginning of a function call tells the compiler to use the function found in global namespace rather than local namespace/class. So:
namespace Wrapper {
void Analytics::SanSetApplicationContext(const char *ctx) {
::SanSetApplicationContext(ctx);
}
}
Should call the c version correctly

Automatically cast values to required type - C#

I use a dll to controll some hardware, and there are two versions of the hardware (and the dll). Some functions have changed, but most of the functions provided by the dll have stayed the same - except that in the newer version, parameters are always provided as Int32, UInt32, and in the old version it was short and ushort.
I created a wrapper class for both versions of the dll that inherits from the dll and provides additional features and masks the functions that acutally did change. By just changing one using, the programm can than be compiled for the old or the new version, and I don't have to write and maintain a big chunk of code twice.
But now I am starting to redefine every function of the dll because of the changed signature like this, which isn't exactly fun:
class ABCWrapper : ABC_V1
{
...
public new static void jump_abs(Int32 x_abs, Int32 y_abs)
{
ABC_V1.jump_abs((short)x_abs, (short)y_abs);
}
...
}
Is there any way to do this automatically, like defining sth. as "Is function inherited from ABC_V1? Yes -> Try explicit cast of parameter" or something?

Import C++ Class Method from C#

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++".

P/Invoke C++ template<T> method from C#

I have defined in C++ function for external calls:
template<typename T>
void __declspec(dllexport) SwapMe(T *fisrt, T *second)
{
std::cout << typeid(T).name() << std::endl;
T temp = *first;
*first = *second;
*second = temp;
}
I want to use it in C# program. I've tried in this way:
unsafe class Program
{
[DllImport("lib1.dll", EntryPoint = "SwapMe")]
static extern void SwapMe<T>(T first, T second);
...
}
But, I'm getting such error:
Generic method or method in generic class is internal call, PInvoke, or is defined in a COM Import class.
Seems to be, that Generic in C# is managed type and it's rather different stuff by architecture with unmanaged template in C++.
How can I use template method in my C# program?
Template functions are not burnt into the binary by the C++ compiler. Only specialized versions are ever emitted. The C++ compiler logically clones the template definition and replaces T with whatever concrete type is wanted.
This means that you must create a specialized wrapper:
void __declspec(dllexport) SwapMe(int *fisrt, int *second) { //example
{ SwapMe(first, second); }
You can call this one from C#, But you cannot call the template version.
C++ templates and C# generics work very differently.
To add to the above, we recently went through this and used T4 (TextTransform.exe) to generate templates for the wrappers in C++.
To do this, we included a T4 file in the C++ project and for each combination of type args, generated a wrapper method around the C++ template method. The wrapper method was then exported.
Finally in C# we did the same, using T4 to generate a generic wrapper around the exported methods. This way you bridge the divide between .NET Generics and C++ templates while harnessing the full awesomeness of C++ Templates

Exposing a C++ API to C#

So what I have is a C++ API contained within a *.dll and I want to use a C# application to call methods within the API.
So far I have created a C++ / CLR project that includes the native C++ API and managed to create a "bridge" class that looks a bit like the following:
// ManagedBridge.h
#include <CoreAPI.h>
using namespace __CORE_API;
namespace ManagedAPIWrapper
{
public ref class Bridge
{
public:
int bridge_test(void);
int bridge_test2(api_struct* temp);
}
}
.
// ManagedBridge.cpp
#include <ManagedBridge.h>
int Bridge::bridge_test(void)
{
return test();
}
int Bridge::bridge_test2(api_struct* temp)
{
return test2(temp);
}
I also have a C# application that has a reference to the C++/CLR "Bridge.dll" and then uses the methods contained within. I have a number of problems with this:
I can't figure out how to call bridge_test2 within the C# program, as it has no knowledge of what a api_struct actually is. I know that I need to marshal the object somewhere, but do I do it in the C# program or the C++/CLR bridge?
This seems like a very long-winded way of exposing all of the methods in the API, is there not an easier way that I'm missing out? (That doesn't use P/Invoke!)
EDIT: Ok, so I've got the basics working now thanks to responses below, however my struct (call it "api_struct2" for this example) has both a native enum and union in the C++ native code, like the following:
typedef struct
{
enum_type1 eEnumExample;
union
{
long lData;
int iData;
unsigned char ucArray[128];
char *cString;
void *pvoid;
} uData;
} api_struct2;
I think I have figured out how to get the enum working; I've re-declared it in managed code and am performing a "native_enum test = static_cast(eEnumExample)" to switch the managed version to native.
However the union has got me stumped, I'm not really sure how to attack it.. Ideas anyone?
Yes, you are passing an unmanaged structure by reference. That's a problem for a C# program, pointers are quite incompatible with garbage collection. Not counting the fact that it probably doesn't have the declaration for the structure either.
You can solve it by declaring a managed version of the structure:
public value struct managed_api_struct {
// Members...
};
Now you can declare the method as
int bridge_test2(managed_api_struct temp); // pass by value
or
int bridge_test2(managed_api_struct% temp); // pass by reference
Pick the latter if the structure has more than 4 fields (~16 bytes). The method needs to copy the structure members, one-by-one, into an unmanaged api_struct and call the unmanaged class method. This is unfortunately necessary because the memory layout of a managed structure is not predictable.
This is all pretty mechanical, you might get help from SWIG. Haven't used it myself, not sure if it is smart enough to deal with a passed structure.
A completely different approach is to make the wrapper class cleaner by giving it a constructor and/or properties that lets you build the content of an api_struct. Or you could declare a wrapper ref class for the structure, much like you would in managed code.
as it has no knowledge of what a api_struct actually is
You need to define a managed version in a .NET assembly, that uses attributes (like StructLayoutAttribute) to ensure it marshals correctly.
This seems like a very long-winded [...]
The other approach is to create a COM wrapper (e.g. using ATL) around your API. This might be more effort, but at least you avoid the double coding of struct and function definitions needed for P/Invoke.
Correction: You have created a C++/CLI project: so just add correct '#pragma' to tell the compiler this is .NET code, and then the output is an assembly the C# project can just reference.
Yuo are trying to do this way more complicated that it really is. What you want is two different structs. One managed and one unmanaged. You expose the managed version externally (to your C# app). It will be all ".Net-ish" with no concepts of unions or so.
In your bridge you receive the managed version of the struct, manually create the unmanaged struct and write code to move your data, field by field over to the unmanaged struct. Then call your unmanaged code and finally move the data back to the managed struct.
The beautiful thing about C++/CLI is that the managed code also can work with unmanaged code and data (and include the unmanaged .h files).

Categories