Вызывание неуправляемой функции от C#: я должен передать StringBuilder или использовать небезопасный код?

Существует три способа сделать это, в зависимости от Ваших потребностей. Вы могли использовать олдскульный путь C и назвать fopen/fread/fclose, или Вы могли использовать C++ fstream средства (ifstream/ofstream), или если Вы используете MFC, используйте класс CFile, который обеспечивает функции для выполнения фактических операций файла.

Все они подходят и для текста и для двоичного файла, хотя ни один не имеет определенную readline функциональность. Что Вы, скорее всего, сделали бы, вместо этого в этом случае использование fstream классы (fstream.h), и используйте потоковые операторы (< < и>>), или чтение функционируют к блокам чтения-записи текста:

int nsize = 10;
char *somedata;
ifstream myfile;
myfile.open("<path to file>");
myfile.read(somedata,nsize);
myfile.close();

Примечание, что при использовании Visual Studio 2005 или более высокий, традиционный fstream не могут быть доступными (существует новая реализация Microsoft, которая немного отличается, но выполняет то же самое).

6
задан John M Gant 6 November 2009 в 13:32
поделиться

5 ответов

Я бы очень предпочел использовать версию StringBuilder.

Между ними не будет большой разницы, а использование небезопасного кода не так чисто.

На мой взгляд, По мнению авторов, поскольку существует способ решить проблему с использованием класса базовой библиотеки, использование небезопасного кода без явных (и необходимых) преимуществ является преждевременной оптимизацией.

8
ответ дан 8 December 2019 в 17:23
поделиться

Хотя использование StringBuilder является предпочтительным, есть одно предостережение. Представьте, например, что в вашем методе getNextResponse вы сохраняете указатель на некоторую статическую переменную и используете его в другом методе:

char* globalPointer;

int getNextResponse(char *buffer) {
    globalPointer = buffer;
    return 0;
}

void someOtherMethod() {
    printf("%s\n", globalPointer);
}

Теперь давайте посмотрим на управляемую сторону:

var sb = new StringBuilder();
sb.Append("Hello World");
int result = getNextResponse(sb);
Console.WriteLine(result);
someOtherMethod(); // kaboom: The GC could have already destroyed the string builder.

Небезопасный метод гарантирует вам, что ячейка памяти не будет перемещаться:

byte[] buffer = Encoding.UTF8.GetBytes("Hello World");
fixed (byte* p = buffer)
{
    int result = getNextResponse(p);
    Console.WriteLine(result);
    someOtherMethod(); // works fine as the buffer address is pinned down in memory
}

В этом случае небезопасная версия будет работать лучше.

3
ответ дан 8 December 2019 в 17:23
поделиться

Хотя я не могу точно взвесить все, я могу поделиться своим собственным опытом. Я использовал исключительно метод StringBuilder и не имел с ним никаких проблем. Мне нравится более простой код и избегание небезопасных вещей.

2
ответ дан 8 December 2019 в 17:23
поделиться

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

1
ответ дан 8 December 2019 в 17:23
поделиться

Это зависит от того, какие данные в буфере на самом деле. Если это символьные данные, используйте подход StringBuilder. Если это двоичные данные, используйте вместо этого массив байтов, но не используйте небезопасный метод. Хотя преувеличенный страх «небезопасности», который становится обычным явлением, немного глуп, и нет причин не использовать его, когда это оправдано, в данном случае в этом нет необходимости. Используйте:

//at class level...
[DllImport("mydll.dll")]
static extern int getNextResponse([In, Out] byte[] buffer);

//in main method body...
byte[] buffer = new byte[65536];
int rc = getNextResponse(buffer);
0
ответ дан 8 December 2019 в 17:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: