我正在尝试P调用C库以在Xamarin安卓应用程序上使用。
考虑以下C结构:
typedef struct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
float myFloatArray[1024];
float myFloatArray2[1024];
float myFloatArray3[20];
float myFloatArray4[30];
} sMyStruct;
使用以下函数调用:
unsigned int initialise(sMyStruct* a_pMyStruct)
我把它放到C#结构中:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct SMyStruct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
public fixed float myFloatArray[1024];
public fixed float myFloatArray2[1024];
public fixed float myFloatArray3[20];
public fixed float myFloatArray4[30];
public unsafe float[] MyFloatArray
{
get
{
fixed (float* ptr = myFloatArray)
{
float[] array = new float[1024];
Marshal.Copy((IntPtr)ptr, array, 0, 1024 * sizeof(float));
return array;
}
}
}
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
}
这是我在C#中的函数来调用它:
[DllImport("libMylib")]
private static extern unsafe uint initialise(SMyStruct* a_pMyStruct);
然后我用以下方法调用此函数:
public unsafe void init ()
{
SMyStruct initStruct;
uint result = initialise(&initStruct);
}
所以会发生什么是C函数将使用大量数据返回我的结构。然后我再次将结构传递给另一个C程序,该程序将这些参数用于程序的其余部分。
我的问题是如何将float数组数据恢复到正确的结构变量中,以便我可以再次传递它?目前,我的代码基于以下问题: Marshalling float Array to c#和 Marshalling complex struct to c#
但我没有成功编写代码,因此我可以将float数组传递回我的结构,甚至没有看到编译器错误(更不用说在测试时失败了!)
如何将float数组数据放入我的结构中?
修改 经过几个答案和评论后,我正在添加我最初做的事情,试图增加一些清晰度。
我遇到编译器错误,而不是使用上面的“public unsafe float [] ...”例程,我这样做(在struct中):
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat, float* MyFloatArray, float* MyFloatArray2, float* MyFloatArray3, float* MyFloatArray4)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
myFloatArray = MyFloatArray;
myFloatArray2 = MyFloatArray2;
myFloatArray3 = MyFloatArray3;
myFloatArray4 = MyFloatArray4;
}
使用此代码,我收到错误“您不能使用未固定表达式中包含的固定大小缓冲区。请尝试使用fixed语句” 此时我尝试使用复制例程。
我想要的是确保填充初始化函数返回的字段myFloatArray,myFloatArray2等。 FYI myBool,sOtherStruct等就像我期望的那样填充。
答案 0 :(得分:0)
如果您不需要访问数据,可以将其保留为指针。虽然您看起来对内存负责,但您需要分配并稍后释放您正在使用的非托管内存。有点像...
[DllImport("libMylib")]
private static extern uint initialise(IntPtr a_pMyStruct);
[DllImport("libMylib")]
private static extern uint anotherNativeMethod(IntPtr a_pMyStruct);
//...
//How big is myOtherStruct??
int size = 1 + ?? + 4 + 4 + (1024*4) + (1024*4) + (20*4) + (30*4);
//int size = Marhsal.SizeOf(SMyStruct);
IntPtr pMyStruct = Marshal.AllocHGlobal(size);
initialise(pMyStruct);
anotherNativeMethod(pMyStruct);
Marshal.FreeHGlobal(pMyStruct);
请注意,您仍然可以使用获取Marshaller使用Marshal.PtrToStructure
将指针复制到您的结构,但您不再需要依赖它来代码。
答案 1 :(得分:0)
我怀疑你的许多问题是由于你在行走之前试图跑步造成的。您试图使用许多成员创建复杂的结构。在一个地方犯一个错误,任何地方都无济于事。
那么,我们如何简化呢?那么,你问的问题与固定缓冲区有关。用你要问的问题来解释:
如何将数组复制到固定缓冲区和从固定缓冲区复制?
让我们通过使用仅包含固定缓冲区的简化类型来处理它,并证明我们可以复制到该缓冲区和从该缓冲区复制。
你的财产获取者是在正确的方向。最大的问题是你传递的长度不正确。您调用的MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc.navigationBar setTintColor:[UIColor whiteColor]];
[mc setSubject:[NSString stringWithFormat:@"V%@ Support", version]];
[mc setMessageBody:supportText isHTML:NO];
[mc setToRecipients:@[@"ring@ringid.com"]];
[self presentViewController:mc animated:YES completion:NULL];
重载的最后一个参数是元素的数量。您错误地传递了字节数。二传手的性质与吸气剂非常相似。这一切看起来像这样:
mc.navigationBar.translucent = NO;
[mc.navigationBar setTintColor:[UIColor myColor]];
mc.navigationBar.backgroundColor = [UIColor myColor];
UIImage *image = [UIImage imageNamed:@"nav-bar_6_plus.png"];
[mc.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
该计划的输出是:
0 0 0 0 1 2 3 4 5 6 0 0
此building block向您展示如何处理固定缓冲区。您可以使用此程序中的代码,并确保正确处理固定缓冲区。当您转移到更复杂的结构时,如果您遇到任何问题,您可以确信它们与固定缓冲区代码无关。