C#到非托管C++;

C#到非托管C++;,c#,c++,marshalling,C#,C++,Marshalling,我在我的C#代码中创建了两个结构: 以及: 在C++代码中,调用C++ dll:函数 [DllImport("DLL_RaFTmodel.dll", CharSet = CharSet.Ansi)] public static extern IntPtr DLL_FlesCalculation(MultiRollCSharp multiRollInfo, CoilInformation

我在我的C#代码中创建了两个结构:

以及:

<>在C++代码中,调用C++ dll:

函数
[DllImport("DLL_RaFTmodel.dll", CharSet = CharSet.Ansi)] 
        public static extern IntPtr DLL_FlesCalculation(MultiRollCSharp multiRollInfo, 
                                              CoilInformationCSharp coilInfo, 
                                              RollInformationCSharp rollInfo, 
                                              LimitsTypeCSharp LimitsSteel, 
                                              LimitsTypeCSharp LimitsRegulation, 
                                              LimitsTypeCSharp LimitsMachine, 
                                              FTInputsCsharp forceTensionInfo, 
                                              RaConstantsCSharp RaModelIn, 
                                              FTWeightCsharp FTmodelIn, 
                                              [In, MarshalAs(UnmanagedType.I4)] int strategy, 
                                              [In, MarshalAs(UnmanagedType.I4)] int rollLifeMaximization, 
                                              RaInputsCsharp RaDataIn, 
                                              char Version, 
                                              [In, MarshalAs(UnmanagedType.R4)] float errMax, 
                                              [Out, MarshalAs(UnmanagedType.I4)] out int error); 
在C++中,我还有2个结构:

struct RollInformation 
{ 
    double rollDiameter; 
    double initialRoughnessRoll; 
    double finalRoughnessRoll; 
    double accumulateCombination; 
    double percentageLifeRoll; 
    double criticalRollLength; 
    double rolledLength; 
    char rollName[256]; 
}; 

该函数还声明如下:

extern EXPORTTOTEM_API  
MULTICURVETYPE* DLL_FlesCalculation( struct MultiRollInformation *multiRollInfo,                                     struct CoilInformation *coilInfo,  
             struct RollInformation *rollInfo, 
             struct LimitsType *LimitsSteel, 
             struct LimitsType *LimitsRegulation, 
             struct LimitsType *LimitsMachine, 
             struct FTInputs *forceTensionInfo, 
             struct RaConstants *constRaIn, 
             struct FTWeight *modelFTIn, 
             int strategy, 
             int rollLifeMaximization, 
             struct RaInputs *dataRaIn, 
                         char Version, 
             float errMax, 
             int &error);    
用C#填充结构的示例:

MultiRollCSharp multiRollInfo=new MultiRollCSharp();
对于(int i=0;i<5;i++)
{ 
RollInformationCSharp rollInfo1=GetRollInformation();
int-taille=0;
if(multiRollInfo.tabRoll!=null)
taille=multiRollInfo.tabRoll.Length;
RollInformationCSharp[]选项卡=新的RollInformationCSharp[taille+1];
如果(尾部>0)
{ 
multiRollInfo.tabRoll.CopyTo(制表符,0);
} 
tab[tab.Length-1]=rollInfo1;
multiRollInfo.tabRoll=tab;
multiRollInfo.nbRoll+=1;
} 
在调试模式下,在调用DLL之前,C#中的两个结构都是正确的(multiRollInfo和rollInfo) . 在C++中,RoLink是好的。但是多重滚动信息有5个元素,但是这些值是错误的

怎么了? 我怎样才能纠正这个问题


非常感谢您的帮助

,您的实现如下所示,如下所示的C++结构(请注意Ext*)。实际上,C代码中的元素属于引用类型(
class
),这意味着它们的本机表示形式是指针

struct MultiRollInformation 
{ 
    int nbRoll; 
    RollInformation** tabRoll; 
};

要解决这个问题,您需要使
RollInformationCSharp
class a
struct
。同时,您必须为托管代码签名的第三参数,为<代码> DLLFLealStudio< <代码> >代码> REF> /COD>参数。

< P>您的实现将其视为声明了以下C++结构(请注意“额外”)。实际上,C代码中的元素属于引用类型(
class
),这意味着它们的本机表示形式是指针

struct MultiRollInformation 
{ 
    int nbRoll; 
    RollInformation** tabRoll; 
};
要解决这个问题,您需要使
RollInformationCSharp
class a
struct
。同时,您必须为
ref
参数的
DLL\u FlesCalculation
创建托管签名的第三个参数。

如果我理解: 在C++中,只有一个修改:

struct MultiRollInformation
{
    int nbRoll;
    RollInformation** tabRoll;
};
在C#中:

要调用的DLL中的函数:

  [DllImport("DLL_RaFTmodel.dll", CharSet = CharSet.Ansi)]
    public static extern IntPtr DLL_FlesCalculation(MultiRollCSharp multiRollInfo,
                     CoilInformationCSharp coilInfo,
                     ref RollInformationCSharp rollInfo,
                     LimitsTypeCSharp LimitsSteel,
                     LimitsTypeCSharp LimitsRegulation,
                     LimitsTypeCSharp LimitsMachine,
                     FTInputsCsharp forceTensionInfo,
                     RaConstantsCSharp RaModelIn,
                     FTWeightCsharp FTmodelIn,
                     [In, MarshalAs(UnmanagedType.I4)] int strategy,
                     [In, MarshalAs(UnmanagedType.I4)] int rollLifeMaximization,
                     RaInputsCsharp RaDataIn,
                     char Version,
                     [In, MarshalAs(UnmanagedType.R4)] float errMax,
                     [Out, MarshalAs(UnmanagedType.I4)] out int error);
在C#中调用此函数时,我在第3个参数上添加ref

在C++中,函数的签名不改变:

extern EXPORTTOTEM_API 
MULTICURVETYPE* DLL_FlesCalculation( struct MultiRollInformation *multiRollInfo,
    struct CoilInformation *coilInfo, 
    struct RollInformation *rollInfo,
    struct LimitsType *LimitsSteel,
    struct LimitsType *LimitsRegulation,
    struct LimitsType *LimitsMachine,
    struct FTInputs *forceTensionInfo,
    struct RaConstants *constRaIn,
    struct FTWeight *modelFTIn,
    int strategy,
    int rollLifeMaximization,
    struct RaInputs *dataRaIn,
    char Version,
    float errMax,
    int &error);   
这样,当调用DLL_FlesCalculation时,它会崩溃。

如果我理解: 在C++中,只有一个修改:

struct MultiRollInformation
{
    int nbRoll;
    RollInformation** tabRoll;
};
在C#中:

要调用的DLL中的函数:

  [DllImport("DLL_RaFTmodel.dll", CharSet = CharSet.Ansi)]
    public static extern IntPtr DLL_FlesCalculation(MultiRollCSharp multiRollInfo,
                     CoilInformationCSharp coilInfo,
                     ref RollInformationCSharp rollInfo,
                     LimitsTypeCSharp LimitsSteel,
                     LimitsTypeCSharp LimitsRegulation,
                     LimitsTypeCSharp LimitsMachine,
                     FTInputsCsharp forceTensionInfo,
                     RaConstantsCSharp RaModelIn,
                     FTWeightCsharp FTmodelIn,
                     [In, MarshalAs(UnmanagedType.I4)] int strategy,
                     [In, MarshalAs(UnmanagedType.I4)] int rollLifeMaximization,
                     RaInputsCsharp RaDataIn,
                     char Version,
                     [In, MarshalAs(UnmanagedType.R4)] float errMax,
                     [Out, MarshalAs(UnmanagedType.I4)] out int error);
在C#中调用此函数时,我在第3个参数上添加ref

在C++中,函数的签名不改变:

extern EXPORTTOTEM_API 
MULTICURVETYPE* DLL_FlesCalculation( struct MultiRollInformation *multiRollInfo,
    struct CoilInformation *coilInfo, 
    struct RollInformation *rollInfo,
    struct LimitsType *LimitsSteel,
    struct LimitsType *LimitsRegulation,
    struct LimitsType *LimitsMachine,
    struct FTInputs *forceTensionInfo,
    struct RaConstants *constRaIn,
    struct FTWeight *modelFTIn,
    int strategy,
    int rollLifeMaximization,
    struct RaInputs *dataRaIn,
    char Version,
    float errMax,
    int &error);   

在这种情况下,当调用DLL_FlesCalculation时,它会崩溃。

从技术上讲,您从原始问题中的声明是正确的,因为MultiRollCSharp.tabRoll是指向内存中数组的引用(指针)。顺便说一句,您将RollInformationCSharp和MultiRollCSharp声明为类,错了吗?还是打字错误

但马歇尔勒无法处理如此复杂的情况。所以有两种方法,首先将数组嵌入结构本身:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MultiRollCSharp
{
    [MarshalAs(UnmanagedType.I4)]
    public int nbRoll;
    [MarshalAs(UnmanagedType.ByValArray)]
    public RollInformationCSharp[] tabRoll;
}

<>这必须正确地工作,如果你从C++到C++(数组长度是已知的),但是如果你尝试向后编组失败,因为在这种情况下,表的数组长度对于封送器是未知的。 第二种选择是用实际指针(IntPtr)替换C#中的tabRoll,并相应地进行操作(alloc memory使用Marshal.AllocHGlobal,等等)。在这种情况下,C++结构仍然未被触动。这是一种更复杂的方法,但也更灵活,一般来说,您可以使用IntPtrs做任何事情

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MultiRollCSharp
{
    [MarshalAs(UnmanagedType.I4)]
    public int nbRoll;
    IntPtr tabRoll;
}

好的,从技术上讲,您在原始问题中的声明是正确的,因为MultiRollCSharp.tabRoll是对内存中数组的引用(指针)。顺便说一句,您将RollInformationCSharp和MultiRollCSharp声明为类,错了吗?还是打字错误

但马歇尔勒无法处理如此复杂的情况。所以有两种方法,首先将数组嵌入结构本身:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MultiRollCSharp
{
    [MarshalAs(UnmanagedType.I4)]
    public int nbRoll;
    [MarshalAs(UnmanagedType.ByValArray)]
    public RollInformationCSharp[] tabRoll;
}

<>这必须正确地工作,如果你从C++到C++(数组长度是已知的),但是如果你尝试向后编组失败,因为在这种情况下,表的数组长度对于封送器是未知的。 第二种选择是用实际指针(IntPtr)替换C#中的tabRoll,并相应地进行操作(alloc memory使用Marshal.AllocHGlobal,等等)。在这种情况下,C++结构仍然未被触动。这是一种更复杂的方法,但也更灵活,一般来说,您可以使用IntPtrs做任何事情

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MultiRollCSharp
{
    [MarshalAs(UnmanagedType.I4)]
    public int nbRoll;
    IntPtr tabRoll;
}