Как управлять буфером между C и C#

Проблема

У меня есть сценарий C #, который вызывает функции C через System.Runtime.Interop. Мне удалось вызвать функции C, но у меня возникла проблема с управлением буфером между C и C #.

В моей ситуации C является (производителем )данных, а C #— потребителем.

Моя проблема заключается в том, что когда я читаю данные в C #, иногда я получаю правильное значение, но иногда я получаю NULL.

Эта проблема уже решена. Я вставляю свой неправильный подход И мой правильный подход здесь, чтобы поделиться с вами.

Исходная информация

Код C #является скриптом единства (частью разработки Mono ), а код C находится в Xcode, что означает, что я не могу использовать функции.Net framework в своем коде C.

Неправильный подход (время от времени дает мне NULL)

Вот мой код C (запись в буфер и чтение из буфера):

static char InteropBF[INTEROP_BUFFER_SIZE];
static int mutex = 0;
// for the c code to put its message in buffer
void PutToBuffer(char* name, char* content)
{
    while (mutex>0);
    mutex++;
    strcat(InteropBF, name);
    strcat(InteropBF, ",");
    strcat(InteropBF, content);
    strcat(InteropBF, ",");
    printf("Interop Buffer: %s\n", InteropBF);
    mutex--;
}


// for the C# code to poll and read from C
void* ReadFromBuffer(void* temp)
{
    while (mutex>0);
    mutex++;
    strcpy(temp, InteropBF);
    // memcpy(temp, InteropBF, INTEROP_BUFFER_SIZE);
    strcpy(InteropBF, "");
    mutex--;
    return temp;
}

Я предоставил функцию ReadFromBuffer ()для C#:

[DllImport ("CCNxPlugin")]
public static extern IntPtr ReadFromBuffer(IntPtr temp);

Затем, я вызываю функцию следующим образом:

        IntPtr temp = Marshal.AllocCoTaskMem(8912);
        CCN.ReadFromBuffer(temp);
        string news = Marshal.PtrToStringAuto(temp);
        if(news != "")
        {
            print (news);
        }
        Marshal.FreeCoTaskMem(temp);

Используя этот код, я иногда получаю правильное содержимое буфера, но чаще я получаю NULL из функции Marshal.PtrToStringAuto.

Правильный подход (Всем большое спасибо!)

Я хотел бы вставить мой рабочий код и ссылки, которые я нашел здесь--

Функция C:

struct bufnode
{
    char* name;
    char* content;
    struct bufnode *next;
};

struct bufnode* bufhead = NULL;
struct bufnode* buftail = NULL;
// for the c code to put its message in buffer
void PutToBuffer(char* name, char* content)
{
    struct bufnode *temp = malloc(sizeof(struct bufnode));
    temp->name = malloc(256);
    temp->content = malloc(256);
    strcpy(temp->name,name);
    strcpy(temp->content,content);
    temp->next = NULL;

    if (bufhead == NULL && buftail == NULL) {
        bufhead = temp;
        buftail = temp;
    }
    else if(bufhead != NULL && buftail != NULL){
        buftail->next = temp;
        buftail = temp;
    }
    else {
        printf("Put to buffer error.\n");
    }    
}

// for the C# code to poll and read from C
struct bufnode* ReadFromBuffer()
{
    if (bufhead != NULL && buftail != NULL) {
        // temp->name = bufhead->name;
        // temp->content = bufhead->content;
        // temp->next = NULL;
        struct bufnode* temp = bufhead;
        if (bufhead == buftail) {
            bufhead = NULL;
            buftail = NULL;
        }
        else {
            bufhead = bufhead->next;
        }

        return temp;
    }
    else if(bufhead == NULL && buftail == NULL)
    {
        return NULL;
    }
    else {
        return NULL;
    }
}

C #оболочка:

[StructLayout (LayoutKind.Sequential)]
public struct bufnode 
{
    public string name;
        public string content;
        public IntPtr next;
}


[DllImport ("CCNxPlugin")]
public static extern IntPtr ReadFromBuffer();

Вызов функции в C#:

        CCN.bufnode BufNode;
        BufNode.name = "";
        BufNode.content = "";
        BufNode.next = IntPtr.Zero;

        IntPtr temp = CCN.ReadFromBuffer();
        if(temp != IntPtr.Zero)
        {
            BufNode = (CCN.bufnode)Marshal.PtrToStructure(temp, typeof(CCN.bufnode));
            print(BufNode.name);
            print(BufNode.content);
            Marshal.FreeCoTaskMem(temp);
        }

Резюме

  1. char[] не кажется как хороший буфер между C и C #(, по крайней мере, в моем случае, когда я использую Unity -Mono и Xcode ). Мое предложение состоит в том, чтобы организовать данные в структуру и передать структуру в качестве параметра или возвращаемого значения в C #. Я нашел отличную документацию о передаче классов и структур, но я не нашел ничего о передаче массива символов сам по себе. Поэтому я думаю, что всегда лучше обернуть char[] в структуру или в класс.
  2. Структура C может быть маршалирована как класс C #или структура C #. Передача класса-обертки в неуправляемую функцию в качестве параметра будет работать. Передача структуры-обертки в неуправляемую функцию в качестве параметра также будет работать. Возврат указателя на структуру из неуправляемой функции допустим. Возврат указателя на класс из неуправляемой функции НЕ допустим. (Нашел отличный туториал по этому поводу:http://www.mono-project.com/Interop_with_Native_Libraries#Summary)
5
задан Zening Qu 3 May 2012 в 20:26
поделиться