我在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个元素,但是值是错误的。
有什么问题? 我怎么能纠正这个?
非常感谢你的帮助
答案 0 :(得分:3)
您的实现将其视为声明了以下C ++结构(请注意额外的*)。因此,C#代码中的元素是引用类型(class
),这意味着它们的本机表示是一个指针。
struct MultiRollInformation
{
int nbRoll;
RollInformation** tabRoll;
};
要解决此问题,您需要将RollInformationCSharp
班级设为struct
。同时,您必须为DLL_FlesCalculation
参数的ref
制作托管签名的第3个参数。
答案 1 :(得分: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#中调用此函数时,我在第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时崩溃。
答案 2 :(得分:0)
从技术上讲,原始问题的声明是正确的,因为MultiRollCSharp.tabRoll是内存中数组的引用(指针)。 BTW,您将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 ++(数组长度已知),这必须正常工作,但如果您尝试向后编组,则会失败,因为在这种情况下,marshaller的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;
}