Почему С# и VB.NET неявно маршалируют char * по-другому?
Итак, у меня есть функция, написанная на С++, которая выглядит так...
extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData)
{
// stuff
}
... и я использую его в своем текущем проекте (написанном на С#). Существуют и другие проекты, которые используют эту функцию, написанную в VB, выглядящую так:
Public Declare Function SomeFunction Lib "MyDLL.dll" _
Alias "[email protected]" (ByVal theData As String) As Integer
Итак, я попробовал записать эквивалент в С#, но обнаружил, что использование типа строки на самом деле не работает для меня - строка вернется с теми же данными, с которыми я передал ее. Я попытался использовать "ref string"
вместо этого, чтобы передать строку по ссылке, и я получил нарушение доступа к памяти.
После некоторого копания я обнаружил, что это была правильная реализация в С#:
[DllImport("MyDLL.dll", EntryPoint = "[email protected]")]
public static extern int SomeFunction(StringBuilder theData);
Теперь я знаю, что VB.NET и С# совершенно разные, но я полагаю, что я всегда считал, что строки были строками. Если один из языков может нести марксировать char*
до String
, почему другой не может потребовать другого класса?
(отредактирован заголовок для ясности)
Ответы
Ответ 1
Теперь я знаю, что VB.NET и С# совершенно разные, но я полагаю, что я всегда считал, что строки были строками
Строки неизменяемы в .net. Спросите себя, почему передача ByVal
неизменяемого типа данных может привести к изменению значения. Этого не происходит для обычных функций, только для Declare
.
Я бы предположил, что все это связано с поддержанием некоторой обратной совместимости с операторами Declare
от классического VB6, которые были сделаны таким образом. На мой взгляд, черная овца здесь - код VB.net, а не код С#.
Ответ 2
Потому что они разные языки. VB.NET может многое из того, что С# не может по многим причинам. Я не вижу, чтобы проблема была честной.
Я должен добавить, что вы могли бы просто сделать ref char [], и это сработало бы. Одна из проблем, которые я вижу, заключается в том, что ваши соглашения о вызове не совпадают.
Так что, вероятно, причина, по которой вы получили ошибку исключения памяти.
Ответ 3
Так как строка является неизменной для начала, я предполагаю, что VB каким-то образом активирует вызов, позволяющий изменять буфер функцией. Возможно, внутри VB также передает StringBuilder.
Я бы не удивился, если бы это было дизайнерское предложение команды VB, чтобы сделать API более похожим на VB6.