Because the company has always been engaged in C ++ development, because the customer needs to provide the C # version interface, I studied C # and found that it is powerful and concise, it is completely encapsulated in cross-language calls and provides powerful API interaction. this is much more convenient than JNA. both Java and C # can only call the C format to export the dynamic library, because C has a single data type and is easy to map. both of them provide a set of ing C #/java description interfaces on the local end, which can be called through the underlying processing of this ing relationship.
I.Transfer of struct
Cpp Code
- # Define JNAAPI extern "C" _ declspec (dllexport) // export functions in C mode
- Typedef struct
- {
- Int osVersion;
- Int majorVersion;
- Int minorVersion;
- Int buildNum;
- Int platFormId;
- Char szVersion [128];
- } OSINFO;
- // 1. Get version information (passing the struct pointer)
- JNAAPI bool GetVersionPtr (OSINFO * info );
- // 2. Get version information (Transfer struct reference)
- JNAAPI bool GetVersionRef (OSINFO & info );
You can call the following two methods:
C # code
- // OSINFO Definition
- [StructLayout (LayoutKind. Sequential)]
- Public struct OSINFO
- {
- Public int osVersion;
- Public int majorVersion;
- Public int minorVersion;
- Public int buildNum;
- Public int platFormId;
- [Financialas (UnmanagedType. ByValTStr, SizeConst = 128)]
- Public string szVersion;
- }
1. method 1Struct referenceIn C #, the struct is passed by passing the value, and the class is passed by passing the address. Add the keyword ref. two different types of parameters are passed on the C-end, which can be solved through reference.
C # code
- [DllImport ("jnalib. dll", EntryPoint = "GetVersionPtr")]
- Public static extern bool GetVersionPtr (ref OSINFO info );
- Public static extern bool GetVersionRef (ref OSINFO info );
2. method 2 (Input IntPtr(Universal platform pointer ))
Cpp Code
- IntPtr pv = Marshal. AllocHGlobal (148); // The struct must be allocated space (4 * sizeof (int) + 128) during use)
- Marshal. WriteInt32 (pv, 148); // write a value to the memory block
- If (GetVersionPtr (pv) // directly takes the unhosted memory block address as the parameter
- {
- Console. WriteLine ("-- osVersion: {0}", Marshal. ReadInt32 (pv, 0 ));
- Console. WriteLine ("-- Major: {0}", Marshal. ReadInt32 (pv, 4); // move 4 bytes
- Console. WriteLine ("-- BuildNum:" + Marshal. ReadInt32 (pv, 12 ));
- Console. WriteLine ("-- szVersion:" + Marshal. PtrToStringAnsi (IntPtr) (pv. ToInt32 () + 20 )));
- }
- Marshal. FreeHGlobal (pv); // after processing, remember to release the memory.
II.Transfer of struct Arrays
Cpp Code
- // Pass the struct pointer
- JNAAPI bool GetVersionArray (OSINFO * info, int nLen );
Call code:
C # code
- /**
- * C # interface. For an array type, only IntPtr can be passed.
- */
- [DllImport ("jnalib. dll", EntryPoint = "GetVersionArray")]
- Public static extern bool GetVersionArray (IntPtr p, int nLen );
- // Source target parameter
- OSINFO [] infos = new OSINFO [2];
- For (int I = 0; I <infos. Length; I ++)
- {
- Infos [I] = new OSINFO ();
- }
- IntPtr [] ptArr = new IntPtr [1];
- PtArr [0] = Marshal. AllocHGlobal (Marshal. SizeOf (typeof (OSINFO) * 2); // assign an array containing two elements
- IntPtr pt = Marshal. AllocHGlobal (Marshal. SizeOf (typeof (OSINFO )));
- Marshal. Copy (ptArr, 0, pt, 1); // Copy the pointer Array
- GetVersionArray (pt, 2); // call
- // Restore to a struct Array
- For (int I = 0; I <2; I ++)
- {
- Infos [I] = (OSINFO) Marshal. ptrToStructure (IntPtr) (pt. toInt32 () + I * Marshal. sizeOf (typeof (OSINFO), typeof (OSINFO ));
- Console. WriteLine ("OsVersion: {0} szVersion: {1}", infos [I]. osVersion, infos [I]. szVersion );
- }
III.Transfer of complex struct
1. output parameters. The struct is used as the pointer to output data.
Cpp Code
- Typedef struct
- {
- Char name [20];
- Int age;
- Double scores [30];
- } Student;
- // Class contains the struct array type
- Typedef struct
- {
- Int number;
- Student students [50];
- } Class;
- // Pass in complex struct Test
- JNAAPI int GetClass (Class * pClass, int len );
Cpp Code
- // Interface Definition
- [DllImport ("jnalib. dll", EntryPoint = "GetClass")]
- Public static extern int GetClass (IntPtr pv, int len );
- // Struct Definition
- // Student
- [StructLayout (LayoutKind. Sequential)]
- Public struct Student
- {
- [Financialas (UnmanagedType. ByValTStr, SizeConst = 20)]
- Public string name;
- Public int age;
- [Financialas (UnmanagedType. ByValArray, SizeConst = 30)]
- Public double [] scores;
- }
- // Class
- [StructLayout (LayoutKind. Sequential)]
- Public struct Class
- {
- Public int number;
- [Financialas (UnmanagedType. ByValArray, SizeConst = 50)] // specify the array size
- Public Student [] students; // struct array Definition
- }
- // Call the complex struct Test
- Int size = Marshal. SizeOf (typeof (Class) * 50;
- IntPtr pBuff = Marshal. AllocHGlobal (size); // directly allocate space for 50 elements, which is much easier than Marshal. copy.
- GetClass (pBuff, 50 );
- Class [] pClass = new Class [50];
- For (int I = 0; I <50; I ++)
- {
- IntPtr ptr = new IntPtr (pBuff. ToInt64 () + Marshal. SizeOf (typeof (Class) * I );
- PClass [I] = (Class) Marshal. PtrToStructure (ptr, typeof (Class ));
- }
- Marshal. FreeHGlobal (pBuff); // release the memory
2. input parameters. assign values to the complex struct and pass them as input parameters.
For large struct pointers, you cannot directly apply the struct type to the IntPtr type. In this case, you need to convert the native type to the pointer and assign a value to the pointer.
Call method: Marshal. StructureToPtr (stu, ptr1, true)