0

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

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
        public class RollInformationCSharp 
        { 
            [MarshalAs(UnmanagedType.R8)] 
            public double rollDiameter; 

            [MarshalAs(UnmanagedType.R8)] 
            public double initialRoughness; 

            [MarshalAs(UnmanagedType.R8)] 
            public double finalRoughness; 

            [MarshalAs(UnmanagedType.R8)] 
            public double accumulateCombination; 

            [MarshalAs(UnmanagedType.R8)] 
            public double critialRollLength; 

            [MarshalAs(UnmanagedType.R8)] 
            public double rolledLength; 

            [MarshalAs(UnmanagedType.R8)] 
            public double percentageLifeRoll; 

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 256)] 
            public string rollName; 
         }; 

和 :

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

            public RollInformationCSharp[] tabRoll; 
        } 

在 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]; 
}; 

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

该函数也声明如下:

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(); 
            for(int i = 0; i < 5; i++) 
            { 
                RollInformationCSharp rollInfo1 = GetRollInformation(); 
                int taille = 0; 
                if (multiRollInfo.tabRoll != null) 
                    taille = multiRollInfo.tabRoll.Length; 

                RollInformationCSharp[] tab = new RollInformationCSharp[taille +1]; 
                if (taille > 0) 
                { 
                    multiRollInfo.tabRoll.CopyTo(tab, 0); 
                } 
                tab[tab.Length-1] = rollInfo1; 
                multiRollInfo.tabRoll = tab; 

                multiRollInfo.nbRoll += 1; 
            } 

在调试模式下,就在调用 DLL 之前,C# 中的两个结构都是正确的(multiRollInfo 和 rollInfo)。在 C++ 中,rollInfo 很好。但是多卷信息有 5 个元素,但值是错误的。

怎么了?我该如何纠正?

非常感谢您的帮助

4

3 回答 3

3

您的实现将其视为声明了以下 C++ 结构(注意额外的 *)。照原样,C# 代码中的元素属于引用类型 ( class),这意味着它们的本机表示是指针。

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

要解决这个问题,您需要将RollInformationCSharp类设为struct. 同时,您必须为参数创建托管签名的第三DLL_FlesCalculationref参数。

于 2009-07-17T06:50:11.773 回答
0

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

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

在 C# 中:

    public struct RollInformationCSharp
    {
        [MarshalAs(UnmanagedType.R8)]
        public double rollDiameter;
        public double initialRoughness;
        public double finalRoughness;
        public double accumulateCombination;
        public double critialRollLength;
        public double rolledLength;
        public double percentageLifeRoll;

        [MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 256)]
        public string rollName;
    };
   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class MultiRollCSharp
    {
        [MarshalAs(UnmanagedType.I4)]
        public int nbRoll;

        public RollInformationCSharp[] tabRoll;
    }

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# 中调用这个函数时,我在第三个参数上添加了 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 时它会崩溃。

于 2009-07-17T08:49:19.177 回答
0

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

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

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

struct MultiRollInformation 
{ 
    int nbRoll; 
    RollInformation tabRoll[];
};

如果您从 C# 编组到 C++(数组长度已知),这必须正常工作,但如果您尝试向后编组,则失败,因为在这种情况下,编组器不知道 tabRoll 数组的长度。

第二个选项是用实际指针 (IntPtr) 替换 C# 中的 tabRoll 并相应地执行(使用 Marshal.AllocHGlobal 分配内存,等等)。在这种情况下,您的 c++ 结构保持不变。这是一种更复杂但也更灵活的方法,通常你可以使用 IntPtrs 完成所有操作。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MultiRollCSharp
{
    [MarshalAs(UnmanagedType.I4)]
    public int nbRoll;
    IntPtr tabRoll;
}
于 2009-07-17T14:07:40.197 回答