I have a somewhat difficult problem with rewriting a C++ application into C#. Basically the C++ application includes a C header file that contains structure and enum definitions:
Imagine it like this:
Header file:
/********** myHeader.h *************/
#ifndef MY_HEADER_H
#define MY_HEADER_H
#define MY_CONSTANT 10u
#define OTHER_CONSTANT 20u
typedef enum
{
ACTION_ONE,
ACTION_TWO,
NUMBER_OF_ACTIONS
} myEnum;
typedef struct
{
uint32_t member;
uint32_t bitfield_msb : 24;
uint32_t bitfield_lsb : 8;
} myStruct;
#endif
So currently the C++ program references these structures. It gets the format from the .h file and constructs structures based on this data. The header itself is also included in a C project. This ensures the compatibility between two projects as they both use identical data structures.
Can anybody recommend a good way of implementing this in C#? Or is it mission impossible. Ofcourse I could define the structures separately in C# format, but in that case the connection between the C project and the (C++ to be translated to C# project) would be lost.
Related
I have this c++ header:
// BRepPrimAPI_MakeSphere.hxx file
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <BRepPrim_Sphere.hxx>
#include <BRepPrimAPI_MakeOneAxis.hxx>
class gp_Pnt;
class gp_Ax2;
class BRepPrimAPI_MakeSphere : public BRepPrimAPI_MakeOneAxis
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT BRepPrimAPI_MakeSphere(const Standard_Real R);
Standard_EXPORT Standard_Address OneAxis();
Standard_EXPORT BRepPrim_Sphere& Sphere();
protected:
private:
BRepPrim_Sphere mySphere;
};
and this c++ source:
// BRepPrimAPI_MakeSphere.cxx file
#include <BRepBuilderAPI.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <gp.hxx>
#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
BRepPrimAPI_MakeSphere::BRepPrimAPI_MakeSphere(const Standard_Real R) :
mySphere(gp::XOY(),R)
{
}
Standard_Address BRepPrimAPI_MakeSphere::OneAxis()
{
return &mySphere;
}
BRepPrim_Sphere& BRepPrimAPI_MakeSphere::Sphere()
{
return mySphere;
}
Standard_EXPORT is defined as follows:
# define Standard_EXPORT __declspec( dllexport )
DEFINE_STANDARD_ALLOC is defined as follows:
# define DEFINE_STANDARD_ALLOC
void* operator new (size_t theSize)
{
return Standard::Allocate (theSize);
}
void operator delete (void* theAddress)
{
Standard::Free (theAddress);
}
void* operator new[] (size_t theSize)
{
return Standard::Allocate (theSize);
}
void operator delete[] (void* theAddress)
{
Standard::Free (theAddress);
}
void* operator new (size_t, void* theAddress)
{
return theAddress;
}
void operator delete (void*, void*)
{
}
I want to use them in my c# code.
I have tried three methods that didn't work for me:
Wrapping the c++ code with CLR to manage it and then use it in the c# code.
SWIG
P/Invoke
Now the issue is that this is one class in a huge c++ library. What I am trying to do is automatically generate the warppers for every single class so I can have the library's full functionality.
The main problem I'm having is handling return types and arguments.
This is what I'm trying right now:
extern "C" __declspec(dllexport) void Call_BRepPrimAPI_MakeSphere(BRepPrimAPI_MakeSphere* p, const Standard_Real R) {
p->BRepPrimAPI_MakeSphere::BRepPrimAPI_MakeSphere(R);
}
But I obviously can't use this in c# because the two argument types don't exist in c# right?
Basically my question is how and what would be the best way to wrap this class?
Basically my question is how and what would be the best way to wrap this class?
I would use c++/cli, that should let you define .Net wrappers that can interact directly with native c++ objects.
What I am trying to do is automatically generate the warppers for every single class so I can have the library's full functionality.
I do not think this can be done in general, at least not without extra knowledge about resource management and other details not expressed in the c++ source. Just consider if a C# object is disposed, should you delete the underlying C++ object? To decide this you need to know if the object is shared or not, and there is no general way to know this.
But creating and using c++/cli code is kind of a pain. You need to have a fair bit of in depth knowledge of c#, c++ and c++/cli. In some cases there are just no alternative, but I would consider other solutions first, like .Net native libraries, or rewriting the required functions in C#.
I am writing interfaces of objective-c class so that objective C methods can be called from my C# code. in the objective-c class they have used "__darwin_size_t"
#ifndef _SIZE_T
#define _SIZE_T
typedef __darwin_size_t size_t;
#endif /* _SIZE_T */
from the above code I can understand that __darwin_size_t is some datatype and "size_t" name can be used for same in this project. I am writing interface in C# language so I need to use some similar datatype that is available in c#. somewhere after this I found a bit more code like bellow
#if defined(__SIZE_TYPE__)
typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */
#else
typedef unsigned long __darwin_size_t; /* sizeof() */
#endif
So I think I can use UInt64 (unsigned long) data type for size_t and Int64 for long long in my c# code.
Please suggest.
Thanks
Vishnu Sharma
My suggestion was fine in the bottom part of my question. I think very few people are working on Xamarin cross platform development tool right now.
Vishnu
I wrote a native C++ library that does some math and simulations using Visual Studio 2013. I'd like to have this library easily usable from VBA and .NET (C#). Being able to easily call it from pure C would be also desired, but not necessary.
The internals of the library are quite complex and I want to expose a facade library for the clients. The API will have just a couple of functions (about 5). Each of the functions will only take 2 pointers as parameters - input and output structures.
My first idea was to create a COM DLL in C++. It seems to be easy to integrate with a COM DLL from VBA and C#. Calling COM from pure C is also possible. But I read the creating COM DLLs in C++ is painful, so I dropped that idea.
My next idea is to create a pure C DLL. I'll define the functions and all input and output nested structs in a C header file, so it's reusable both from C and C++. Here's an excerpt:
#pragma pack(push)
#define MF_MAX_PERIODS 240
#define MF_MAX_REGIONS 60
typedef enum mf_agency_model_type { FNMA, FHLMC } mf_agency_model_type;
/* BEGIN OF INPUT DATA STRUCTURES */
/* VBA structs are packed to 4 byte boundaries. */
#pragma pack(4)
typedef struct mf_boarding_loans {
int regions_count;
double timeline[MF_MAX_REGIONS];
} mf_boarding_loans;
#pragma pack(4)
typedef struct mf_agency_model_input {
mf_agency_model_type model_type;
int periods_count;
mf_boarding_loans boarding_loans;
} mf_agency_model_input;
/* BEGIN OF OUTPUT DATA STRUCTURES */
#pragma pack(4)
typedef struct mf_curves {
double dd_90_rate[MF_MAX_PERIODS];
double dd_60_rate[MF_MAX_PERIODS];
} mf_curves;
#pragma pack(4)
typedef struct mf_agency_model_output{
double wal_years;
mf_curves curves;
} mf_agency_model_output;
#pragma pack(pop)
/* BEGIN OF EXTERN FUNCTIONS */
#ifdef __cplusplus
extern "C" {
#endif
/* VBA requires _stdcall calling convention. */
MFLIB_API void _stdcall mf_run_agency_model(mf_agency_model_input *model_input, mf_agency_model_output *model_output);
#ifdef __cplusplus
}
#endif
It should be possible to call such a DLL from C/C++, VBA (via DECLARE) and C# (via PInvoke). The problem is the amount of input and output data. Ultimately, my input data structures will contain about 70 parameters (numbers and arrays of numbers), and the outputs will contain about 100 variables (also numbers and arrays of numbers). I presume that I'd have to declare the same structures both in VBA and C# again and I'd really like to avoid that. (I think I could avoid the declaration in VBA if I expose the C# code as COM to VBA. It seems to be very easy to impelement COM in C#.) My goal is to define the structures only once. Here are my questions:
1) I quickly read about C++/CLI. Could C++/CLI compile my C header to .NET MSIL so it's usable from other .NET languages without any wrappers? I think there will still be a problem with exposing the object to VBA via COM, since it requires some attributes to be added to classes/interfaces, but macros should help here.
2) Is there a tool that will generate for me the structures declarations in VBA and C# from the C code? I'm also OK with having to declare the structures in some meta language and generate C, VBA and C# structures from that.
3) Is it better to define my arrays as fixed size in C or just raw pointers? I read somewhere that it's easier for interop if the arrays have fixed size.
4) Is it better to include the child structures in the parent directly or via pointers from the interop perspective?
Is there any other way that will free me from redefining the huge data structures in multiple languages?
Thanks for your help,
Michal
Is there a way to share an enum definition between native (unmanaged) C++ and (managed) C#?
I have the following enum used in completely unmanaged code:
enum MyEnum { myVal1, myVal2 };
Our application sometimes uses a managed component. That C# component gets the enum item values as ints via a managed C++ interop dll (from the native dll). (The interop dll only loads if the C# component is needed.) The C# component has duplicated the enum definition:
public enum MyEnum { myVal1, myVal2 };
Is there a way to eliminate the duplication without turning the native C++ dll into a managed dll?
You can use a single .cs file and share it between both projects. #include in C++ on a .cs file should be no problem.
This would be an example .cs file:
#if !__LINE__
namespace MyNamespace
{
public
#endif
// shared enum for both C, C++ and C#
enum MyEnum { myVal1, myVal2 };
#if !__LINE__
}
#endif
If you want multiple enums in one file, you can do this (although you have to temporarily define public to be nothing for C / C++):
#if __LINE__
#define public
#else
namespace MyNamespace
{
#endif
public enum MyEnum { MyEnumValue1, MyEnumValue2 };
public enum MyEnum2 { MyEnum2Value1, MyEnum2Value2 };
public enum MyEnum3 { MyEnum3Value1, MyEnum3Value2 };
#if __LINE__
#undef public
#else
}
#endif
Thanks for sharing!
I played around a bit and found a way to have multiple enum and constant declarations without having tons of extra lines :)
// This is a valid C, C++ and C# file :)
#if __LINE__
#define public
#else
namespace MyCSharpNamespace{
#endif
public enum MyConstant { MaxStr = 256 };
public enum MyEnum1{ MyEnum1_A, MyEnum1_B };
public enum MyEnum2{ MyEnum2_A, MyEnum2_B };
#if __LINE__
#undef public
#else
}
#endif
Remember to name your file *.cs
You can expose the C# library to COM and then import the type library into the unmanaged code - this way you will be able to use the enum defined in C# library in the unmanaged library.
Unmanaged C++ and C# live in two different worlds, so no there is no way to use the same enum, without changing the c++ DLL into a managed one.
And even then, you'd probably need the duplication in the managed C++ DLL.
A C++ enum is much like a list of constants, whereas a C# enum inherits the Enum class, and thus provides quite a few "tricks". So as you can see, they're very different.
If it doesn't matter whether the native C++ DLL is native or managed, I'd turn it into a managed one and wrap the native calls inside a managed C++ Layer.
That way you can have the enum duplication inside the C++ DLL, and also you can get rid of all the interop at the same time :-)
I've had the same problem in the past and solved it using preprocessor definitions.
In your unmanaged code, inside a header that can also be included by your managed wrapper, place your enumeration items into a #define.
Then, in your managed and unmanaged enumeration definitions, use the same #define for both usages.
The movement of the enumerations between the managed and unmanaged world looks slightly nasty (basically a cast is needed), but to your caller in the unmanaged world, it'll look and feel fine.
Good luck,
I know how to extern methods in the .dll, how do I extern structs?
I want to create a C method such as
extern __declspec(dllexport) myStructure getStruct();
where myStructure is something like
typedef struct
{
int A;
int B;
char C;
} myStructure;
How can I call getStruct() from a piece of C# code without first defining the same exact struct in C#? I want to keep a centralized declaration of myStructure so that I only have to make code changes in one place.
Thanks a bunch!
What about doing it another way? Define the struct in C# in T4 and then cross gen to the new format in each of the projects:
ie. base.tt
// C# definition of struct
in gencsharp.tt in the C# project
include "base.tt"
... output the C#
in gencplusplus.tt in the CPP project
include "base.tt"
... use C# to gen a cpp .h file
I've done a bit of P/Invoke with C# and I've always had to define structs in C# that correspond to the Win32 struct by definition. The runtime uses the struct definition to marshal the data from unmanaged to managed. Preet's answer is probably the best.