Передача сложной структуры C++ в C#
Я потратил много часов, проверяя другие статьи и экспериментируя с различными методами, пытаясь решить эту. Я пытаюсь перенести устаревший код с C++ на C#, и часть этого переноса включает в себя преобразование существующих файлов данных в новые форматы.
Из многих прочитанных мною эта статья представляется наиболее актуальной
c# - импорт функции из c++, возвращающей structure-Stack Overflow[^]
однако структуры, которые я портирую, не так просты и включают массивы.
Я также ссылался на эту статью
Разоблачение native для managed-C++ / CLI против P / Invoke[^]
Я сделал комментарии в приведенном ниже коде относительно областей, которые я в настоящее время получаю с несколькими попытками.
Главная проблема заключается в том, что основная структура также включает в себя массивы других структур, которые я с большим трудом передаю в свой код C#.
Любая помощь или указания на этот счет будут оценены по достоинству. Я постарался сделать код как можно более кратким, а также показать, в чем заключаются проблемы, и быть описательным в коде.
Единственная проблема (я думаю) - это вложенные массивы структур. C# ограничивает это объявление в структуре, поэтому мне пришлось довольствоваться указателями
Что я уже пробовал:
Это то, что я имею в настоящее время после слишком многих попыток
Код C++
namespace CPlusPlusDLL { #define MAX_DESCRIPTION_LENGTH 255 #define MAX_INSTALLATIONS 46 #define MAX_CONFIGURATIONS 14 #pragma pack(1) typedef struct { short row; unsigned char column; short table; } TABLE_TYPE; typedef struct { struct { short version; char description[MAX_DESCRIPTION_LENGTH]; char something; } INSULATION_HEADER; struct { char code[MAX_DESCRIPTION_LENGTH]; TABLE_TYPE tableDetails[MAX_INSTALLATIONS]; } val_struc[MAX_CONFIGURATIONS]; } DEFINITION; public ref class ManagedWrapper { public: static DEFINITION* ReturnStructObjectFunc(int defIndex) { DEFINITION* def = new DEFINITION(); (*def).INSULATION_HEADER.version = 1; strcpy_s((*def).INSULATION_HEADER.description, "description"); (*def).INSULATION_HEADER.something = 'C'; // ... Populate the rest of the structure here and all the arrays. return def; }; }; extern "C" __declspec(dllexport) DEFINITION* ReturnStructObjectDLLImport(int defIndex) { DEFINITION* def = new DEFINITION(); (*def).INSULATION_HEADER.version = 1; strcpy_s((*def).INSULATION_HEADER.description, "description"); (*def).INSULATION_HEADER.something = 'C'; // ... Populate the rest of the structure here and all the arrays. return def; }; }
Код C#
namespace CSharpDLL { public class Wrapper { const int maxDescLength = 255; const int maxInstalls = 46; const int maxConfigs = 14; [StructLayout( LayoutKind.Sequential )] unsafe public struct LegacyInsulationHeader { short version; // Can use a fixed array here as this is a primitive type. fixed char description[maxDescLength]; char something; } [StructLayout( LayoutKind.Sequential )] unsafe public struct LegacyTableType { short row; byte column; short table; }; [StructLayout( LayoutKind.Sequential )] unsafe public struct LegacyConfiguration { fixed char code[maxDescLength]; // Cannot do this because it is a struct and not a primitive type. fixed LegacyTableType tableDetails[maxInstalls]; // which leaves me having to use a pointer here. LegacyTableType* tableDetails; } [StructLayout( LayoutKind.Sequential )] unsafe public struct LegacyDefinition { LegacyInsulationHeader INSULATION_HEADER; // Cannot do this because it is a struct and not a primitive type. fixed LegacyConfiguration val_struc[maxConfigs]; // which leaves me having to use a pointer here. LegacyConfiguration* val_struc; }; [DllImport( "CPlusPlusDLL.dll", SetLastError = true )] internal static extern IntPtr ReturnStructObjectDLLImport( int insulationType ); public static void ConvertStruct(int index) { unsafe { LegacyDefinition *definition = null; // This call fails to build as it is returning a struct * and I get the error // CPlusPlusDLL.ManagedWrapper.ReturnStructObjectFunc( 0 ) is inaccessible // due to its protection level // If I change the return type to int or void however the protection level // is not an issue definition = CPlusPlusDLL.ManagedWrapper.ReturnStructObject( 0 ); // The following code gives me this error at run time // Additional information: A call to PInvoke function // 'InteropTesting!CSharpDLL.Wrapper::ReturnStructObjectDLLImport' has unbalanced the stack. // This is likely because the managed PInvoke signature does not match the unmanaged target // signature. Check that the calling convention and parameters of the PInvoke signature // match the target unmanaged signature. ReturnStructObjectDLLImport(index); } } } }
Консольное Тестовое Приложение C#
namespace WinConsoleTestApp { class Program { static void Main( string[ ] args ) { int a = 0; CSharpDLL.Wrapper.ConvertStruct( 0 ); a++; } } }