Я пишу библиотеку C, с которой мне нужно взаимодействовать из Unity3D (C#), и у меня возникла проблема с записью одного из моих вызовов PInvoke.
У меня есть следующая структура c
typedef struct TestStruct
{
const char* Method;
const char* Url;
} TestStruct;
И подпись функции C
__declspec(dllexport) void __cdecl TestMethod(TestStruct* args)
{
// Do stuff with Method and URL
}
В C# я создал свою структуру так
[StructLayout(LayoutKind.Sequential)]
public struct TestStruct
{
public string Method;
public string Url;
}
И подпись PInvoke вот так
[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(TestStruct args);
Теперь, когда я запускаю это в редакторе Unity на Win64, он работает нормально. Но когда я развертываю его на своем устройстве Android (Nexus 6, который, как я считаю, представляет собой 32-битную архитектуру ARM), свойства Method и Url в моей тестовой структуре равны нулю, когда они попадают в C lib.
Как ни странно, если я изменю свои сигнатуры функций, чтобы принимать необработанные аргументы, полностью избегая структуры, это работает нормально.
__declspec(dllexport) void __cdecl TestMethod(const char* Method, const char* Url)
{
// Do stuff with Method and URL
}
а также
[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(string method, string url);
Работает нормально. Есть ли у кого-нибудь идеи, что я делаю не так?
Ух ты. Спасибо. Это было точно на месте. Не могли бы вы опубликовать это как ответ, чтобы я мог принять это как решение?





Этот:
__declspec(dllexport) void __cdecl TestMethod(TestStruct* args)
эквивалентно:
[DllImport("Test", CallingConvention = CallingConvention.Cdecl)]
private static extern void TestMethod(ref TestStruct args);
или out TestStruct, в зависимости от того, кто будет писать в TestStruct.
Важно: если string передаются C-> C#, то C# не должен изменять их (иначе .NET попытается освободить их с помощью неправильного деаллокатора, и произойдет что-то плохое). Если вы используете out TestStruct, сторона C должна будет освободить возвращенный const char*, я должен сказать, что не знаю, как именно (потому что вы используете Unity, а не .NET под Windows, поэтому все становится немного более волосатым)
(TestStruct args)должен быть(ref TestStruct args)...