Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling C code from C# - stuck with a couple of issues

Tags:

c

c#

I have some C code that and I trying to use from C#. Most of the conversion is done. I have a couple of issues though.

Part of the 'C' code looks like this.

typedef struct r_GetCPL {

  UInt8 Storage;
  UInt8 Key[16];             //(1) 

  UInt8 *Buff;               //(2)
  Array16 *CryptoKeyIDs;     //(3)

} REPLY_GETCPL;

alias defined in 'C'

typedef unsigned char      UInt8;
typedef unsigned short     UInt16;
typedef unsigned long      UInt32;
typedef unsigned long long UInt64;

typedef UInt8   Array8[8];
typedef UInt8   Array16[16];
typedef UInt8   Array32[32];
typedef UInt8   Array64[64];
typedef UInt8   Array128[128];

I am assuming I can replace the typedef with a direct struct definition. Is this fine? The equivalent C# struct I defined is,

public struct REPLY_GETCPL 
{
  Byte Storage;
  Byte[16] Key;          //(1) Is this right?

  UInt8 *Buff;           //(2)  What is the equivalent?
  Array16 *CryptoKeyIDs; //(3)  What is the equivalent?
}

Also, There are a couple of methods import that I am stuck at

void hex_print(char* data, UInt32 length);
DRMKLVItem *NewDRMKLVItem(UInt32 lenBuff, UInt32 cmdId);
RESULT DRMKLVLengthDecode(const UInt8 *s, UInt32 *pLen);

C#

//I think this one is defined right
[DllImport("DoremiSource.dll")]
public static extern void hex_print([MarshalAs(UnmanagedType.LPStr)]string data, UInt32 length);

//(How to convert the function return type?)
[DllImport("DoremiSource.dll")]
public static extern DRMKLVItem *NewDRMKLVItem(UInt32 lenBuff, UInt32 cmdId);  //(4)

//(How do i convert the function parameters here)
[DllImport("DoremiSource.dll", CharSet = CharSet.Ansi)]
public static extern int DRMKLVLengthDecode(const UInt8 *s, ref UInt32 pLen);  //(5)
like image 831
ShaQ.Blogs Avatar asked Oct 29 '12 09:10

ShaQ.Blogs


People also ask

Can I mix C and C++ code?

C and C++ are two closely related programming languages. Therefore, it may not come as a surprise to you that you can actually mix C and C++ code in a single program. However, this doesn't come automatically when you write your code the normal way.

Can I use C libraries in C++?

Sure ... C code is called from C++ all the time. For instance, most OS libraries are written in C rather than C++. So whenever you're making syscalls from your C++ code to perform tasks that are handed over to the OS kernel, those are going through C-code calls.

Can I call C from rust?

Rust can link to/call C functions via its FFI, but not C++ functions. While I don't know why you can't call C++ functions, it is probably because C++ functions are complicated. You can just define C linkage on any C++ function, making it available from C and thus also Rust. extern "C" is your friend here.

What is extern C used for?

extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block. In a template declaration, extern specifies that the template has already been instantiated elsewhere.


1 Answers

You can use complex types and marshal them around between C and C#, you just have to know about the compilation option for the structure, then decorate a C# type like the following: (From MSDN)

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}
like image 188
Hylaean Avatar answered Sep 25 '22 10:09

Hylaean