struct MyStruct1
{
unsigned char id;//0-1
int width;//4-8
long long height;//8-16
unsigned char* data;//16-20
};
struct MyStruct2
{
char username[10];//0-10
int width;//12-16
};
struct MyStruct3
{
int width;//0-4
double height;//8-16
unsigned char* data;//16-20
MyStruct2 myStruct2;//20-30 32-36 最大成员8的整数倍40
};
int main()
{
int size1 = sizeof(MyStruct1); //24
int size2 = sizeof(MyStruct2); //16
int size3 = sizeof(MyStruct3); //40
return 0;
}
#define FIELDOFFSET(TYPE,MEMBER) (int)(&(((TYPE*)0)->MEMBER))//宏定义字段偏移量
int main()
{
int size1 = sizeof(MyStruct1); //24
int size2 = sizeof(MyStruct2); //16
int size3 = sizeof(MyStruct3); //40
int width= FIELDOFFSET(MyStruct3, width);//0
int height= FIELDOFFSET(MyStruct3, height);//8
int data= FIELDOFFSET(MyStruct3, data);//16
int myStruct2= FIELDOFFSET(MyStruct3, myStruct2);//20
return 0;
}
///结构体中的对齐方式
#pragma pack(push)
#pragma pack(1)
struct MyStruct4
{
int width;//0-4
double height;//4-12
unsigned char* data;//12-16
};
#pragma pack(pop)
public struct TestStruct1
{
public byte id;
public int width;
public double height;
public int num;
}
[StructLayout(LayoutKind.Explicit)]
public struct TestStruct2
{
[FieldOffset(0)]
public byte id;
[FieldOffset(10)]
public int width;
[FieldOffset(20)]
public double height;
[FieldOffset(30)]
public int num;
}
[StructLayout(LayoutKind.Sequential,Pack =1)]
public struct TestStruct3
{
public byte id;
public int width;
public double height;
public int num;
}
class Program
{
static void Main(string[] args)
{
TestStruct1 testStruct1 = new TestStruct1();
TestStruct2 testStruct2 = new TestStruct2();
TestStruct3 testStruct3 = new TestStruct3();
int len1 = Marshal.SizeOf(testStruct1);//24
int len2 = Marshal.SizeOf(testStruct2);//40
int len3 = Marshal.SizeOf(testStruct3);//17
Console.ReadKey();
}
}
C# | C/C++ |
---|---|
ubyte | char |
byte | unsigned char |
short | short |
int32 | int32_t |
long | int64_t |
float | float |
double | double |
IntPtr,[] | void* |
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
#ifdef DLL_IMPORT
#define HEAD EXTERNC __declspec(dllimport)
#else
#define HEAD EXTERNC __declspec(dllexport)
#endif
#define CallingConvention _cdecl
HEAD void CallingConvention Test1();
#include "Native.h"
#include
#include
HEAD void CallingConvention Test1()
{
printf("call success\n");
}
#include
#include
#define DLL_IMPORT
#include "../NactiveDll/Native.h"
#pragma comment(lib, "../bin/Nactivedll.lib")
int main()
{
Test1();
return 0;
}
只需要将.cpp改成.c将C++的特有的头文件改成C的即可
[DllImport("NactiveDll.dll")]
public static extern void Test1();
static void Main(string[] args)
{
Test1();
Console.ReadKey();
}
//.h
HEAD void CallingConvention TestCharSet(const char* log);
//.cpp
HEAD void CallingConvention TestCharSet(const char* log)
{
printf("log:%s\n", log);
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void TestCharSet(string log);
//调用
TestCharSet("Test");
TestCharSet("测试");
//.h
HEAD void CallingConvention TestEntryPoint(const char* log);
//.cpp
HEAD void CallingConvention TestEntryPoint(const char* log)
{
printf("log:%s\n", log);
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestEntryPoint")]
public static extern void TestEntryPoint2(string log);
//调用
TestEntryPoint2("测试EntryPoint");
//.h
HEAD void CallingConvention TestLogA(const char* log);
HEAD void CallingConvention TestLogW(const char* log);
//.cpp
HEAD void CallingConvention TestLogA(const char* log)
{
printf("logA:%s\n", log);
}
HEAD void CallingConvention TestLogW(const char* log)
{
printf("logW:%s\n", log);
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestLog",ExactSpelling =true)]
public static extern void TestLog(string log);
//调用
TestLog("测试ExactSpelling");//如果ExactSpelling =true,则会匹配EntryPoint = "TestLog",因为动态链接库中没写TestLog,只有TestLogA和TestLogW,所以会报错
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestLog",ExactSpelling =false,CharSet =CharSet.Unicode)]
public static extern void TestLog(string log);
//调用
TestLog("测试ExactSpelling");//如果ExactSpelling =false,则会根据CharSet的编码格式来,如果CharSet =CharSet.Unicode,则调用TestLogW,否则会调用TestLogA
///如果有TestLog函数,则不管ExactSpelling 设置为false还是true都会调用TestLog函数而不是TestLogA或者TestLogB
//.h
HEAD void CallingConvention TestSetLastError(const char* log);
//.cpp
HEAD void CallingConvention TestSetLastError(const char* log)
{
SetLastError(3);
printf("log:%s\n", log);
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl, SetLastError =true)]
public static extern void TestSetLastError(string log);
//调用
int ret = Marshal.GetLastWin32Error();//0
TestSetLastError("测试SetLastError");
ret = Marshal.GetLastWin32Error();//3
//.h
HEAD float CallingConvention Test_Add(float num1, float num2);
//.cpp
HEAD float CallingConvention Test_Add(float num1, float num2)
{
return num1 + num2;
}
//C#调用
[DllImport("NactiveDll.dll", CharSet = CharSet.Ansi)]
public static extern float Test_Add(float num1,float num2);
//调用
float f = Test_Add(1.1f,2.2f);
//.h
HEAD void CallingConvention Test_BasicDataRef(char& d1, short& d2, int& d3, long long& d4, float& d5, double& d6);
//.cpp
HEAD void CallingConvention Test_BasicDataRef(char& d1, short& d2, int& d3, long long& d4, float& d5, double& d6)
{
d1 = 1;
d2 = 2;
d3 = 3;
d4 = 4;
d5 = 5.5f;
d6 = 6.6;
}
//C#调用
[DllImport("NactiveDll.dll", CharSet = CharSet.Ansi)]
public static extern float Test_BasicDataRef(ref sbyte d1, ref short d2, ref int d3, ref long d4, ref float d5, ref double d6);
//调用
sbyte d1=0; short d2 = 0; int d3 = 0; long d4 = 0; float d5 = 0; double d6 = 0;
Test_BasicDataRef(ref d1,ref d2,ref d3,ref d4,ref d5,ref d6);
//.h
HEAD void CallingConvention Test_BasicDataPointer(char* d1, short* d2, int* d3, long long* d4, float* d5, double* d6);
//.cpp
HEAD void CallingConvention Test_BasicDataPointer(char* d1, short* d2, int* d3, long long* d4, float* d5, double* d6)
{
*d1 = 10;
*d2 = 20;
*d3 = 30;
*d4 = 40;
*d5 = 15.5f;
*d6 = 16.6;
}
//C#调用
[DllImport("NactiveDll.dll", CharSet = CharSet.Ansi)]
public static extern float Test_BasicDataRef(ref sbyte d1, ref short d2, ref int d3, ref long d4, ref float d5, ref double d6);
//调用
sbyte d1=0; short d2 = 0; int d3 = 0; long d4 = 0; float d5 = 0; double d6 = 0;
Test_BasicDataPointer(ref d1, ref d2, ref d3, ref d4, ref d5, ref d6);
//.h
HEAD void* CallingConvention Test_StructRet();
//.cpp
struct FrameInfo
{
char username[20];
double pts;
};
struct Frame
{
int width;
int height;
int format;
int linesize[4];
unsigned char* data[4];
FrameInfo* info;
};
Frame frame;
FrameInfo info;
HEAD void* CallingConvention Test_StructRet()
{
frame.width = 1920;
frame.height = 1080;
frame.format = 0;
for (int i = 0; i < 4; i++)
{
frame.linesize[i] = 100 * i;
frame.data[i] = new unsigned char[10];
for (int j = 0; j < 10; j++)
{
frame.data[i][j] = i;
}
}
info.pts = 12.5;
memset(info.username, 0, 20);//字符串置空
memcpy(info.username, "hello world", strlen("hello world"));
frame.info = &info;
return &frame;
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr Test_StructRet();
//调用
IntPtr ptr = Test_StructRet();
int width = Marshal.ReadInt32(ptr,0);
int height = Marshal.ReadInt32(ptr,4);
int format = Marshal.ReadInt32(ptr,8);
int[] linesize = new int[4];//读取数组
Marshal.Copy(new IntPtr(ptr.ToInt64()+12),linesize,0, linesize.Length);
IntPtr[] datas = new IntPtr[4];//读取指针数组
Marshal.Copy(new IntPtr(ptr.ToInt64()+32), datas, 0,datas.Length);
for (int i = 0; i < datas.Length; i++)
{
byte[] temp = new byte[10];
Marshal.Copy(datas[i],temp,0,temp.Length);
}
IntPtr frameinfo = Marshal.ReadIntPtr(ptr,64);
byte[] username = new byte[20];
Marshal.Copy(frameinfo,username,0,username.Length);
string str = Encoding.ASCII.GetString(username);
double pts =BitConverter.Int64BitsToDouble(Marshal.ReadInt64(frameinfo,24));
//.h
HEAD void* CallingConvention Test_StructRet();
//.cpp
struct FrameInfo
{
char username[20];
double pts;
};
struct Frame
{
int width;
int height;
int format;
int linesize[4];
unsigned char* data[4];
FrameInfo* info;
};
Frame frame;
FrameInfo info;
HEAD void* CallingConvention Test_StructRet()
{
frame.width = 1920;
frame.height = 1080;
frame.format = 0;
for (int i = 0; i < 4; i++)
{
frame.linesize[i] = 100 * i;
frame.data[i] = new unsigned char[10];
for (int j = 0; j < 10; j++)
{
frame.data[i][j] = i;
}
}
info.pts = 12.5;
memset(info.username, 0, 20);//字符串置空
memcpy(info.username, "hello world", strlen("hello world"));
frame.info = &info;
return &frame;
}
//C#调用
[DllImport("NactiveDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr Test_StructRet();
[StructLayout(LayoutKind.Sequential)]
struct FrameInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string username;
public double pts;
};
[StructLayout(LayoutKind.Sequential)]
struct Frame
{
public int width;
public int height;
public int format;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public int[] linesize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.SysUInt)]
public IntPtr[] data;
public IntPtr info;
};
//调用
IntPtr ptr = Test_StructRet();
var value = Marshal.PtrToStructure<Frame>(ptr);
for (int i = 0; i < value.data.Length; i++)
{
byte[] temp = new byte[10];
Marshal.Copy(value.data[i], temp, 0, temp.Length);
}
byte[] username = new byte[20];
Marshal.Copy(value.info, username, 0, username.Length);
string str = Encoding.ASCII.GetString(username);
double pts = BitConverter.Int64BitsToDouble(Marshal.ReadInt64(value.info, 24));