[英]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.