Мне нужно передать аргумент небезопасной функции DllImported в виде:
[DllImport("third_party.dll")]
private static extern unsafe int start(int argc, char** argv);
Я предполагаю, что это массив строк. Однако, когда я пытаюсь сделать следующее, я получаю сообщение об ошибке «Невозможно преобразовать из строки [] в символ **». Как мне заставить это работать? Спасибо.
string[] argv = new string[] { };
start(0, argv);
EDIT 1: Вопрос был помечен как повторяющийся, но, глядя на возможный повторяющийся вопрос, я все еще не понимаю, как заставить его работать.
EDIT 2: Чтобы уточнить вопрос и необходимые параметры. Это похоже на ваши стандартные параметры argc/argv (количество параметров, а затем значения параметров). Так же, как вы запускаете программу на языке C: int main(int argc, char** argv);
Для этой конкретной проблемы я вообще не хочу передавать какие-либо аргументы (поэтому count равен 0).
EDIT 3: я получил дополнительную информацию от стороннего поставщика библиотеки. Вот:
- первый параметр - количество аргументов
второй параметр представляет собой массив строк с завершающим нулем- строки кодируются ANSI
РЕДАКТИРОВАНИЕ 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;
}