Marshalling data for C# - c#

I have not many experience in such language as C# so I would be pleased if you guys could help me. I wrote this method in C++ using MPIR library:
mpz_class SchnorrProtocol::getX(const mpz_class& r) const
{
mpz_class x;
mpz_powm(x.get_mpz_t(), this->params_.getBeta().get_mpz_t(), r.get_mpz_t(), this->params_.getP().get_mpz_t());
return x;
}
and now I want to import it to C#:
#region Filter & P/Invoke
#if DEBUG
private const string DLL = "schnorrd.DLL";
#else
private const string DLL = "schnorr.DLL";
#endif
[DllImport(DLL)]
"method definition"
...... SchnorrProtocol::getX(......);
my problem, I don't know how to do it. Could u please help me?

You have to use structlayout attribute to define mpz_class, i.e.,
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class mpz_class
{
// your class definition
}
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class SchnorrProtocol
{
// your class definition.
}
And here's how you marshal a method inside a C++ class
[ DllImport( DLL,
EntryPoint="?getX#SchnorrProtocol##QAEHH#Z",
CallingConvention=CallingConvention.ThisCall )]
public static extern int TestThisCalling( SchnorrProtocol prot );

Related

Calling C dll from C#, return types slightly different

I've written a dll in C which has functions I can call when referencing the DLL in C#. If I use a basic type like an int it works fine, but I have structs which are slightly different in C# than they are in C due to language differences. Here is an example. This is the function definition in C#:
[DllImport("hello_world_cuda.dll", CharSet = CharSet.Auto)]
public static extern Batch Cut();
And here is it in C:
extern "C" Batch __declspec(dllexport) __stdcall Cut()
You can see the return type Batch is the same, but here is its definition in C#
class Envelope
{
public byte[] Payload;
public byte[] Signature;
}
class Batch
{
public Envelope[] Messages;
public int MsgCount;
}
And here is the definition in C
struct Envelope
{
public:
char* Payload;
char* Signature;
};
struct Batch
{
public:
Envelope* Messages;
int MsgCount;
};
How do I overcome these language differences in order to successfully make the DLL call in C#?
You should define Envelope and Batch as structs in C# too, and apply the StructLaylout attribute:
e.g.:
[StructLayout(LayoutKind.Sequential, Pack=0)]
struct Envelope
{
...
}
Pointers in an unmanaged language do not map to managed arrays as you have done, this is why it is complaining. char is (almost always, with very limited exceptions) an 8 bit value that maps well to byte in C# as you've noticed, but you need to make them pointers in the managed struct as well:
unsafe struct Envelope
{
public byte* Payload;
public byte* Signature;
}

In C# how to access DLL methods written in C++ [duplicate]

I have an unmanaged DLL that exports only a C style factory method that returns a new instance of a class (simplified here to look simple).
hello.h
#if defined(HWLIBRARY_EXPORT) // inside DLL
# define HWAPI __declspec(dllexport)
#else // outside DLL
# define HWAPI __declspec(dllimport)
#endif
struct HelloWorld{
public:
virtual void sayHello() = 0;
virtual void release() = 0;
};
extern "C" HWAPI HelloWorld* GetHW();
hello.cpp
#include "hello.h"
struct HelloWorldImpl : HelloWorld
{
void sayHello(){
int triv;
std::cout<<"Hello World!";
std::cin>>triv;
};
void release(){
this->HelloWorldImpl::~HelloWorldImpl();
};
HelloWorld* GetHW(){
HelloWorld* ptr = new HelloWorldImpl();
return ptr;
};
Now, I can use dllimport to access GetHW() but is there a way to access the member functions of the returned 'struct'... ie, sayHello and release?
I was also stuck with the same problem. This question was asked a while before. I commented to it for any better solution but didn't get any reply yet. So, reposting it.
When i googled, able to find out two solutions.
Solution1: Expose all the member functions in the C-style for the existing dll. Which i cant do, as it is a 3rd party dll.
Solution2: Write a managed C++ dll exposing the functionality of native C++ dll, which later can be used in your C# dll. Here many classes/functions are present. So, creating would take most of the time.
i got the above solutions from the link below.
How To Marshall
Please let me know if there is any better solution other than the above two solutions?
i have the source code for C++ solution. But what i though was not to touch C++ dll. If there is any possibility to do it in C#, it would be great.
If there is no alternative, i need to follow any one of the specified two solutions.
The C++ code is using the way abstract classes are implemented by the Visual C++ compiler. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx. This memory layout is "fixed" because it is used for implementing COM interfaces. The first member of the struct in memory will be a pointer to a vtable containing the function pointers of your methods. So for a
struct HelloWorldImpl : public HelloWorld
{
public:
int value1;
int value2;
}
the "real" layout in memory would be:
struct HelloWorldImpl
{
HelloWorldVtbl *vtbl;
int value1;
int value2;
}
where vtbl would be:
struct HelloWorldVtbl
{
void *sayHello;
void *release;
}
Just for the sake of doing a complete response, I'm writing the example for this signatures:
struct HelloWorld {
public:
virtual int sayHello(int v1, int v2, int v3) = 0;
virtual void release() = 0;
};
C# code:
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetHW();
[StructLayout(LayoutKind.Sequential)]
struct HelloWorldVtbl
{
public IntPtr sayHello;
public IntPtr release;
}
Your functions are void Func(void) or int Func(int, int, int), but in truth they have a hidden parameter, this, so you can write them as:
int sayHello(HelloWorld*, int, int, int);
void release(HelloWorld*);
so in C# the delegate is
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate int Int32MethodInt32Int32Int32(IntPtr ptr, int v1, int v2, int v3);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void VoidMethodVoid(IntPtr ptr);
Then you can use
IntPtr ptr = GetHW();
IntPtr vtbl = Marshal.ReadIntPtr(ptr, 0);
HelloWorldVtblhw = (HelloWorldVtbl)Marshal.PtrToStructure(vtbl, typeof(HelloWorldVtbl));
Int32MethodInt32Int32Int32 sayHello = (Int32MethodInt32Int32Int32)Marshal.GetDelegateForFunctionPointer(hw.sayHello, typeof(Int32MethodInt32Int32Int32));
int res = sayHello(ptr, 1, 2, 3);
Console.WriteLine(res);
VoidMethodVoid release = (VoidMethodVoid)Marshal.GetDelegateForFunctionPointer(hw.release, typeof(VoidMethodVoid));
release(ptr);

Marshalling complex struct from C++ to C#

For a few days now I have been trying to Marshal a complex struct from C++ to C#, basically I have managed to get most of what I am trying to achieve done but now I'm stuck trying to marshal what I believe is a list.
In example I will include what I do get working and where I am stuck.
public: void __thiscall TransactionModule_t::GetTransaction(class Identity_t const &)const
Conformed as follwoing:
// public: void __thiscall TransactionModule_t::GetTransaction(class Identity_t const &)const
[DllImport("Transaction.dll", EntryPoint = "?GetTransaction#TransactionModule_t##Identity_t###Z", CallingConvention = CallingConvention.ThisCall)]
public static extern void GetTransaction(IntPtr iPtr,[Out, MarshalAs(UnmanagedType.LPStruct)] Identity transaction);
[StructLayout(LayoutKind.Sequential)]
[Serializable]
public class Identity
{
public uint Id;
public uint Type;
public Identity(uint id = 0, uint type = 0)
{
this.Id = id;
this.Type = type;
}
}
This is working just fine.
However I want to call a method which gives me the list.
public: void __thiscall TransactionModule_t::GetTransactions(class std::vector<class Identity_t,class std::allocator<class Identity_t> > &)const
And where i am getting stuck:
// public: void __thiscall TransactionModule_t::GetTransactions(class std::vector<class Identity_t,class std::allocator<class Identity_t> > &)const
[DllImport("Transaction.dll", EntryPoint = "long mangled entry point", CallingConvention = CallingConvention.ThisCall)]
public static extern void GetTransactions(IntPtr iPtr,[Out] Transactions transactions);
I tried making a class that fits in between the two.
[StructLayout(LayoutKind.Sequential)]
[Serializable]
public class Transactions
{
public Identity Identity;
public Identity[] List;
}
Is it even possible to call this method, am I missing something here?
Is it even possible to call this method?
No it is not. You cannot supply a std::vector from C# code.
Realistically you are going to need a C++/CLI wrapper.

Importing DLL functions in c# code

I have a DLL, whose functions i want to use in my c# code
Here are the functions of that DLL :
extern "C"
{
__declspec(dllimport)
const char* __stdcall ZAJsonRequestA(const char *szReq);
__declspec(dllimport)
const wchar_t* __stdcall ZAJsonRequestW(const wchar_t *szReq);
__declspec(dllimport)
const BSTR __stdcall ZAJsonRequestBSTR(BSTR sReq);
}
Can anyone tell me how to use it in c# project, as this dll seems to be in other language ?
Please have a look at the following article on Code Project for an in depth explanation
A small sample from the linked article is as shown below
To call a function, say methodName
int __declspec(dllexport) methodName(int b)
{
return b;
}
Include the class library (MethodNameLibrary.dll) containing the above method as shown below in c#
class Program
{
[DllImport(#"c:\MethodNameLibrary.dll")]
private static extern int methodName(int b);
static void Main(string[] args)
{
Console.WriteLine(methodName(3));
}
}
Use DllImport and MarshalAs attributes.

p/invoke calling C dll from c#

this is my C code
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL(string a)
{
printf ("%s\n",a)
}
}
this is my C# code
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL(string a);
static void Main ()
{
string a = "Hello";
DisplayHelloFromDLL(a);
}
}
It built successfully but crash like this:
SO,how to use P/invoke to call my own C dll from C#?
Please help,thanx in advance.
First of all your code is C++ rather than C. Your function receives a parameter of type std::string and the use of std::string means that your code is actually C++.
Now this parameter type is the root of your problem. You cannot create a std::string in .net and instead will need to use a char* to pass the string data. The following code is what you need:
C++
__declspec(dllexport) void DisplayHelloFromDLL(char* a)
{
printf("%s\n", a);
}
C#
[DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DisplayHelloFromDLL(string a);
static void Main ()
{
string a = "Hello";
DisplayHelloFromDLL(a);
}
The default p/invoke marshalling for a .net string is to pass a char* as an [In] parameter. There is no need for the complexity of IntPtr, StringToHGlobalAnsi, FreeHGlobal as suggested by one of the other answers. If you can let the p/invoke marshaller do the work then it is preferable to do so.
Note that you also need to make sure that your calling conventions match. Under the assumption that you have not used any special compiler options when building your C++ code, that code will default to used cdecl calling convention. You can make that match with the CallingConvention parameter to the DllImport attribute.
Please take a look at marshalling string at MSDN
In a nut shell, a C# string doesn't get marshalled as std::string but a char* by default
For one thing the return type is not matching. In C it is void and in C# int.
Change your C++ param type to char* and update your C# code as following
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL(IntPtr a);
static void Main ()
{
string a = "Hello";
var ptr = System.Runtime.Marshal.StringToHGlobalAnsi(a);
DisplayHelloFromDLL(ptr);
System.Runtime.Marshal.FreeHGlobal(ptr);
}
}

Categories

Resources