Мне нужно передать аргумент небезопасной функции DllImported в виде:
[DllImport("third_party.dll")]
private static extern unsafe int start(int argc, char** argv);
Я предполагаю, что это массив строк. Однако, когда я пытаюсь сделать следующее, я получаю сообщение "Невозможно преобразовать из строки [] в char **". Как я могу заставить это работать? Спасибо.
string[] argv = new string[] { };
start(0, argv);
РЕДАКТИРОВАТЬ 1: Вопрос был отмечен как дубликат, но, глядя на возможный дублирующий вопрос, я до сих пор не вижу, как заставить это работать.
РЕДАКТИРОВАТЬ 2: Чтобы добавить clafiry вопрос и необходимые параметры. Он похож на ваши стандартные параметры argc/argv (количество параметров, а затем значения параметров). Точно так же вы можете запустить c-программу: int main(int argc, char** argv);
Для этой конкретной проблемы я не хочу передавать какие-либо аргументы вообще (так что count равно 0).
ИЗМЕНИТЬ 3: Я получил дополнительную информацию от поставщика сторонней библиотеки. Вот он:
- первым параметром является количество аргументов
-
второй параметр представляет собой массив строк с нулевым завершением - строки кодируются ANSI
EDIT 4: окончательное редактирование с рабочим решением (по крайней мере, в моем случае). Я бы ответил на этот вопрос, но не могу, потому что этот вопрос отмечен как дубликат. Здесь ссылка на вопрос, который мне очень помог. В конце функция dll ожидала массив указателей на буферы с цепочками ANSI. Итак, мой окончательный подход (основанный на связанном вопросе) был следующим. Создайте массив в памяти, чтобы удерживать указатели, затем выделяйте каждую строку в другом месте в памяти и указывайте указатели на те строки внутри первого массива указателей. Этот код работает в производстве:
[DllImport("third_party.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int start(Int32 args, IntPtr argv);
public bool start(params string[] arguments)
{
int result;
if (arguments == null || arguments.Length == 0)
{
result = dll_system_startup(0, IntPtr.Zero);
}
else
{
List<IntPtr> allocatedMemory = new List<IntPtr>();
int sizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
IntPtr pointersToArguments = Marshal.AllocHGlobal(sizeOfIntPtr * arguments.Length);
for (int i = 0; i < arguments.Length; ++i)
{
IntPtr pointerToArgument = Marshal.StringToHGlobalAnsi(arguments[i]);
allocatedMemory.Add(pointerToArgument);
Marshal.WriteIntPtr(pointersToArguments, i * sizeOfIntPtr, pointerToArgument);
}
result = start(arguments.Length, pointersToArguments);
Marshal.FreeHGlobal(pointersToArguments);
foreach (IntPtr pointer in allocatedMemory)
{
Marshal.FreeHGlobal(pointer);
}
}
return result == 0;
}