我们在c#和c dll之间编组了以下代码。但是,当打印C dll函数中的值时,与双精度数组属性关联的值均为0.0000000。我对有问题的代码添加了一些注释。
我们是否错过任何配置编组行为的事情?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
MonteCarlo montecarlo = new MonteCarlo();
montecarlo.RunMonteCarlo();
}
}
class MonteCarlo
{
[DllImport("MonteCarloCUDA.dll")]
public static extern int MonteCarloPrint([In, Out]PurchaseOrder[] purchaseorders, int length);
public void RunMonteCarlo()
{
PurchaseOrder[] purchaseorders = new PurchaseOrder[3];
purchaseorders[0] = new PurchaseOrder();
purchaseorders[0].Value1 = "AAAAA";
purchaseorders[0].Value2 = 0.111;
purchaseorders[0].Value3 = new double[2]; // Assign the values to array of double
purchaseorders[0].Value3[0] = 0.11111;
purchaseorders[0].Value3[1] = 0.22222;
purchaseorders[1] = new PurchaseOrder();
purchaseorders[1].Value1 = "BBB";
purchaseorders[1].Value2 = 0.222;
purchaseorders[1].Value3 = new double[2];
purchaseorders[1].Value3[0] = 0.33333;
purchaseorders[1].Value3[1] = 0.44444;
purchaseorders[2] = new PurchaseOrder();
purchaseorders[2].Value1 = "CCC";
purchaseorders[2].Value2 = 0.333;
purchaseorders[2].Value3 = new double[2];
purchaseorders[2].Value3[0] = 0.55555;
purchaseorders[2].Value3[1] = 0.66666;
int result = MonteCarloPrint(purchaseorders, purchaseorders.Length);
Console.ReadKey();
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public unsafe struct PurchaseOrder
{
public string Value1;
public double Value2;
public double[] Value3; // Array of double member
}
}
}
// C代码
#include <stdio.h>
typedef struct PurchaseOrder
{
char* Value1;
double Value2;
double* Value3;
};
__declspec(dllexport) int __stdcall MonteCarloPrint(PurchaseOrder *hostPurchaseOrders, int length)
{
printf("\nSize of PurchaseOrder: %d",sizeof(PurchaseOrder));
for (int i = 0; i < length; i++)
{
printf("\n\nAddress: %u",hostPurchaseOrders+i);
printf("\nValue1: %s",(hostPurchaseOrders+i)->Value1);
printf("\nValue2: %f",(hostPurchaseOrders+i)->Value2);
printf("\nValue3[0]: %f",(hostPurchaseOrders+i)->Value3[0]);
printf("\nValue3[1]: %f",(hostPurchaseOrders+i)->Value3[1]);
}
}}
C dll函数的打印结果
采购订单大小:24
地址:13180880
值1:AAAAA
价值2:0.111000
Value3 [0]:0.000000 //没有值编组
值3 [1]:0.000000
地址:13180904
值1:BBB
价值2:0.222000
值3 [0]:0.000000
值3 [1]:0.000000
地址:13180928
值1:CCC
值2:0.333000
值3 [0]:0.000000
值3 [1]:0.000000
c#参考方案
从[DllImport]声明中删除Pack属性,这是错误的。您没有在C代码中使用#pragma pack指令,Pack的默认值是合适的。如果生效,那么您的C代码将报告为16。
您会看到24,因为当在数组中使用结构时,在结构的末尾有4个填充字节来对齐double,在结构的末尾有4个填充字节来使double对齐。 4 + 4 + 8 + 4 + 4 =24。有效包装是8,默认值。
您可以通过交换Value2和Value3以获得16字节的结构来提高效率,而无需填充。万一重要。这就是JIT编译器所做的。
下一个问题更加棘手,P / Invoke编组将把嵌入式阵列编组为SAFEARRAY。您可以使用以下代码在非托管方面解决此问题:
#include "stdafx.h"
#include <stdio.h>
#include <objidl.h>
struct PurchaseOrder
{
char* Value1;
double Value2;
LPSAFEARRAY Value3;
int fence;
};
extern "C"
__declspec(dllexport) int __stdcall MonteCarloPrint(PurchaseOrder *hostPurchaseOrders, int length)
{
printf("\nSize of PurchaseOrder: %d",sizeof(PurchaseOrder));
for (int i = 0; i < length; i++)
{
printf("\n\nAddress: %u",hostPurchaseOrders+i);
printf("\nValue1: %s",(hostPurchaseOrders+i)->Value1);
printf("\nValue2: %f",(hostPurchaseOrders+i)->Value2);
double* arrayPtr;
if (S_OK == SafeArrayAccessData((hostPurchaseOrders+i)->Value3, (void**)&arrayPtr)) {
printf("\nValue3[0]: %f", arrayPtr[0]);
printf("\nValue3[1]: %f", arrayPtr[1]);
}
}
return 0;
}
我使用C ++编译器编写了代码,您可能需要进行调整。
加载/卸载带有C#问题的C dll - c#我在使用外部本机DLL时遇到问题。我正在ASP.NET 1.1 Web应用程序上工作,并具有通过DLLImport指令加载的此DLL。这就是我映射DLL函数的方式: [DllImport("somedllname", CallingConvention=CallingConvention.StdCall)] public static e…
当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…
Mongo汇总 - javascript我的收藏中有以下文件{ "_id": ObjectId("54490b8104f7142f22ecc97f"), "title": "Sample1", "slug": "samplenews", "cat": …
jQuery DataTable TableTool在IE和Firefox中不起作用 - c#我在MVC4 ASP.NET Web应用程序中使用Jquery DataTable TableTool。导出到Excel和PDF可以与Chrome完美配合。但是不能在IE和FireFox中使用。我的代码如下 dom: 'T<"clear">lfrtip', tableTools: { "sSwfP…
提交表单后显示模式对话框 - php提交下载文件后,我有一张表格。我要自动而不是自动下载文件..以显示模态对话框并显示下载链接。<form name="softwareform" id="softwareform" action="../downloadlink.php" method="POST" alig…