簡體   English   中英

C#轉換為非托管C ++

[英]C# to unmanaged C++

我在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很好。 但是multiroll信息有5個元素,但是值有誤。

怎么了? 我該如何糾正?

非常感謝您的幫助

您的實現將其視為聲明了以下C ++結構(請注意額外的*)。 照原樣,C#代碼中的元素是引用類型( class ),這意味着它們的本機表示形式是指針。

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

為了解決這個問題,您需要使RollInformationCSharp類成為struct 同時,您必須為ref參數的DLL_FlesCalculation托管簽名的DLL_FlesCalculation個參數。

如果我理解:在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#中調用此函數時,我將引用添加到第3個參數上。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM