Dart call the C programming language mix

Dart call the C language
this blog Dart language study how to call C code hybrid programming, we finally achieve a simple example, write a simple encryption and decryption functions in C language, the use of dart call and pass a string and returns the result of encryption, decryption call function, restore the contents of the string.

Environmental ready
compiler environment
GCC VS compiler if not installed, it is recommended to use the GCC compiler, download a 64-bit version of Windows - MinGW-W64
Download


As above, it has two versions, sjlj and suffix seh exception handling model, seh good performance, but does not support 32-bit. Sjlj good stability, support for 32-bit, recommend seh version

The compiler is mounted to the specified directory, after installation, also need to configure the environment variables, the installation bin directory of the system is added to the Path environment variable, comprising gcc.exe, make.exe tools like chain bin directory.

Test environment
After configuration, test to see whether the environment to build a successful, open cmd command line, type gcc -v can check the version number is successful.

Dart SDK environment
destined Dart official website to download the latest 2.3 version of the SDK, note that older versions do not support ffi Download

After downloaded, you also need to configure the environment variables, the dart-sdk \ bin configured into the system Path environment variable.

Dart ffi test the interface
simple example of
creating a test project, open cmd command line

FFI-proj mkdir
cd FFI-proj
mkdir bin src
1
2
3
Create a project directory ffi-proj, create a bin under which, src folder, create main.dart file in the bin, create a file in the src test.c

Test.c write
us in the header file which contains the windows for showBox function, call the Win32 API, create a dialog

#include<windows.h>

int add(int a, int b){
return a + b;
}


void the showBox () {
the MessageBox (NULL, "the Hello Dart", "the Title", MB_OK);
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
into the src directory using gcc compiler, the C language code compiled into dll dynamic storehouse

-shared -o Test.dll test.c gcc
1
write main.dart

import 'dart:ffi' as ffi;
import 'dart:io' show Platform;

/// The function C defined in the method signature (called method signature, a method or function is to be described, including the return type, the parameter type)
/// where signatures need to define two methods, a language is C in, one after converting to Dart
typedef NativeAddSign = ffi.Int32 Function (ffi.Int32, ffi.Int32);
typedef int DartAddSign Function = (int, int);

/// showBox method signature function
typedef NativeShowSign = ffi.Void Function ();
typedef void DartShowSign = Function ();

void main(List<String> args) {
if (Platform.isWindows) {
// 加载dll动态库
ffi.DynamicLibrary dl = ffi.DynamicLibrary.open("../src/test.dll");

// lookupFunction has two functions, one, to find the specified dynamic library function; 2, the Native type C function into the Dart Function type
var add = dl.lookupFunction <NativeAddSign, DartAddSign > ( "add");
var showBox = dl.lookupFunction <NativeShowSign, DartShowSign > ( "showBox");

// add function call
Print (add (. 8,. 9));
// call the function showBox
showBox ();
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23 is
24
25
26
27


In-depth usage
here to write a little bit further example, we write a simple encryption algorithm in C language, and then use the dart call C functions encryption and decryption

Write encrypt_test.c, here to write a simple XOR encryption algorithm, encryption and decryption can be seen virtually identical

#include <string.h>

#define KEY 'abc'

void encrypt(char *str, char *r, int r_len){
int len = strlen(str);
for(int i = 0; i < len && i < r_len; i++){
r[i] = str[i] ^ KEY;
}

if (r_len> len) r [len] = '\ 0';
else r [r_len] = '\ 0';

}

void decrypt(char *str, char *r, int r_len){
int len = strlen(str);
for(int i = 0; i < len && i < r_len; i++){
r[i] = str[i] ^ KEY;
}

IF (r_len> len) R & lt [len] = '\ 0';
the else R & lt [r_len] = '\ 0';
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23
24-
compiled into a dynamic library

gcc encrypt_test.c -shared -o encrypt_test.dll
1
编写main.dart

import 'dart:ffi';
import 'dart:io' show Platform;
import "dart:convert";


/// encrypt function method signature, noted that the methods encrypt and decrypt the signature here is actually the same, two types of function return value and parameter types are identical
typedef NativeEncrypt = Void Function (CString, CString, Int32);
typedef DartEncrypt = void Function (CString, CString, int );


void main(List<String> args) {
if (Platform.isWindows) {
// 加载dll动态库
DynamicLibrary dl = DynamicLibrary.open("../src/encrypt_test.dll");
var encrypt = dl.lookupFunction<NativeEncrypt, DartEncrypt>("encrypt");
var decrypt = dl.lookupFunction<NativeEncrypt, DartEncrypt>("decrypt");


CString data = CString.allocate("helloworld");
CString enResult = CString.malloc(100);
encrypt(data,enResult,100);
print(CString.fromUtf8(enResult));

print("-------------------------");

CString deResult = CString.malloc(100);
decrypt(enResult,deResult,100);
print(CString.fromUtf8(deResult));
}
}

/// to create a class that inherits Pointer <Int8> pointer, processing for mapping the C language strings and Dart string
class CString extends Pointer <Int8> {

/// application memory space, the C language string to string Dart
Factory CString.allocate (String dartStr) {
List <int> Units = Utf8Encoder () Convert (dartStr);.
The Pointer <Int8> = the allocate STR (COUNT : + units.length. 1);
for (int I = 0; I <units.length; I ++) {
str.elementAt (I) .store (Units [I]);
}
str.elementAt (units.length) .store (0);

return str.cast();
}

// application heap memory space specified size
Factory CString.malloc (int size) {
the Pointer <Int8> = the allocate STR (COUNT: size);
return str.cast ();
}

/// C language string into a character string Dart
static String fromUtf8 (CString STR) {
IF (STR == null) return null;
int len = 0;
the while (str.elementAt (++ len) .load <int> () = 0);!
List <int> List Units = (len);
for (int I = 0; I <len; I ++) Units [I] = str.elementAt (I). Load ();
return Utf8Decoder () Convert (Units);.
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23 is
24
25
26 is
27
28
29
30
31 is
32
33 is
34 is
35
36
37 [
38 is
39
40
41 is
42 is
43 is
44 is
45
46 is
47
48
49
50
51 is
52 is
53 is
54 is
55
56 is
57 is
58
59
60
61 is
62 is
run results

You can see the "helloworld" turned into a bunch of garbled string encryption, decryption string after restore content

Improve the code
above code though achieved our goal, but there are obvious memory leaks, we use malloc and allocate CString of the application heap memory, but there is no manual release, you may run out of memory space after this operation for some time, manual management memory is often the C / C ++ in the most problematic areas, where we can carry out a simple design to reclaim memory

// Create Reference CString class tracking application memory
class Reference {
Final List <the Pointer <Void >> _allocations = [];

T ref<T extends Pointer>(T ptr) {
_allocations.add(ptr.cast());
return ptr;
}

// manual release after use memory
void Finalize () {
for (Final PTR in _allocations) {
ptr.free ();
}
_allocations.clear ();
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
to modify the code

import 'dart:ffi';
import 'dart:io' show Platform;
import "dart:convert";


/// encrypt function method signature, noted that the methods encrypt and decrypt the signature here is actually the same, two types of function return value and parameter types are identical
typedef NativeEncrypt = Void Function (CString, CString, Int32);
typedef DartEncrypt = void Function (CString, CString, int );


void main(List<String> args) {
if (Platform.isWindows) {
// 加载dll动态库
DynamicLibrary dl = DynamicLibrary.open("../src/hello.dll");
var encrypt = dl.lookupFunction<NativeEncrypt, DartEncrypt>("encrypt");
var decrypt = dl.lookupFunction<NativeEncrypt, DartEncrypt>("decrypt");

// 创建Reference 跟踪CString
Reference ref = Reference();

CString data = CString.allocate("helloworld",ref);
CString enResult = CString.malloc(100,ref);
encrypt(data,enResult,100);
print(CString.fromUtf8(enResult));

print("-------------------------");

CString deResult = CString.malloc(100,ref);
decrypt(enResult,deResult,100);
print(CString.fromUtf8(deResult));

// manual release after use
ref.finalize ();
}
}

class CString extends Pointer<Int8> {

/// memory it controls, the C language string to string Dart
Factory CString.allocate (String dartStr, [REF Reference]) {
List <int> Units = Utf8Encoder () Convert (dartStr);.
The Pointer <Int8> = the allocate STR (COUNT: units.length +. 1);
for (int I = 0; I <units.length; I ++) {
str.elementAt (I) .store (Units [I]);
}
str.elementAt (units.length) .store (0);

ref?.ref(str);
return str.cast();
}

factory CString.malloc(int size, [Reference ref]) {
Pointer<Int8> str = allocate(count: size);
ref?.ref(str);
return str.cast();
}

/// C language string into a character string Dart
static String fromUtf8 (CString STR) {
IF (STR == null) return null;
int len = 0;
the while (str.elementAt (++ len) .load <int> () = 0);!
List <int> List Units = (len);
for (int I = 0; I <len; I ++) Units [I] = str.elementAt (I). Load ();
return Utf8Decoder () Convert (Units);.
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23 is
24
25
26 is
27
28
29
30
31 is
32
33 is
34 is
35
36
37 [
38 is
39
40
41 is
42 is
43 is
44 is
45
46 is
47
48
49
50
51 is
52 is
53 is
54 is
55
56 is
57 is
58
59
60
61 is
62 is
63 is
64
65
66
67
summarizes
dart: ffi packet currently being processed development temporarily released only basic functions, and the use of dart: after ffi package, aot Dart code can not be compiled, but Dart has developed a ffi interfaces, which greatly extends the ability to dart language boundaries, just as the Java-Jni as if ffi Interface development was good enough, Dart will be able to become a true as glue language like Python.

If you are interested in further research, you can view the dart: ffi source package, the package is currently a total of only five dart files, source code rarely, suitable for learning.
--------------------- 

Guess you like

Origin www.cnblogs.com/ly570/p/10942293.html