Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.7k views
in Technique[技术] by (71.8m points)

Dart ffi - Reading emojis from file with C

I am saving a File with UTF-8 encoding which contains some information including a name for a button from Dart side with the following code:

file.writeAsString([
          name.length.toString(),
          name + Constants.nativeFileDelimeter,
          ids.length.toString(),
          ids.join(" "),
        ].join(" "));

// Constants.nativeFileDelimeter is "|", it is used so that user can enter a name with whitespaces

I read the same file with C and use FFI to pass data between C and Dart.

        FILE *file;

        file = fopen(filePath, "r");

        if (!file) {
            LOGE("Could not open %s!", filePath);
            *operationState = MediaLoadState::FAILED_TO_LOAD;
            goto cleanup;
        }

        int32_t size;

        if(fscanf(file, "%d ", &size) != 1){
            LOGE("fscanf can not assign variables %s!", filePath);
            *operationState = MediaLoadState::FAILED_TO_LOAD;
            goto cleanup;
        }

        // +1 because C strings ends with /0
        *namePtr = new char[size + 1];

        if (size != 0){
            if(fscanf(file, "%[^|]|", *namePtr) != 1){
                LOGE("fscanf can not assign variables %s!", filePath);
                *operationState = MediaLoadState::FAILED_TO_LOAD;
                goto cleanup;
            }
        }

Dart code that reads the pointer saved by C:

  Pointer<Pointer<Utf8>> _namePtrPtr;
  String get name => Utf8.fromUtf8(_namePtrPtr.value);

My problem is this code works with 0 bugs it even works with japanese, russion characters but when emojis are introduced thing get weird. When I save a file containing emojis and I try to read it with C and Dart ffi I get strange errors thrown by Utf8.fromUtf8. for example:

Unfinished UTF-8 octet sequence (at offset 48)

Sometimes the same code it works and renders the emojis but later on the app crashes randomly. The exceptions thrown seems to be different each time I read the file, sometimes I get no exception but later a crash! It is not consistent. I have no idea what I am doing wrong, I expected it to work with emojis. can anyone help me solve this issue?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In Dart, String.length returns the number of UTF-16 code units. For reading UTF-8 in C, you need to know the number of UTF-8 bytes instead. Therefore, output utf8.encode(name).length instead of name.length in the Dart code (and import dart:convert). Exceptions and crashes may be because of undefined behavior triggered by too short size.

Storing the data size separately in a text format is error-prone. Better use this approach:

It seems you are using C++. There, you can just open the file as std::ifstream, create a std::string name; and use std::getline(file, name, '|'); to read the name with dynamic size. You can use *namePtr = strdup(name.c_str()) to create a plain C string out of the std::string.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...