我有C代码,它将构建为动态库(DLL),我想要 使用从C代码创建的dLL从C#调用C函数
struct data
{
char data_val1[100];
float data_val2;
float data_val3[50];
};
typedef struct data data;
#ifdef __cplusplus
extern "C" __declspec(dllexport) void cfun_call(data *pdata,long count);
#endif
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void cfun_call(data *pdata,long count)
{
int x = 0;
for(x=0;x<count;x++)
{
data[x].data_val2 = (pdata->data_val3[49] + pdata->data_val3[48]) / 2.0;
}
}
#ifdef __cplusplus
}
#endif
这里我想导入函数&#34; cfun_call&#34;在C#代码中,并将值传递给fucntion调用 并从dll处理C函数中传递的值,并希望显示更新的值 回到C#代码并显示它,因为我对C#的专业知识有限,我需要一些帮助来解决这个问题
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
class Program
{
public class data
{
public char[] data_val1 = new char[100];
public float data_val2;
public float[] data_val3 = new float[50];
};
[DllImport("mycdll.dll", EntryPoint = "cfun_call", CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)]
// void cfun_call(data *pdata,long count); //C function for reference
public static extern void cfun_call([In, Out] data[] ouputdata, long count);
static void Main(string[] args)
{
data[] objData = new data[10];
for (int i = 0; i < 10; i++)
{
//Fill the data in objitemData
objData[i] = new objData();
for (int j = 0; j < 100; j++)
{
objData[i].data_val1[j] = '\0';
}
for (int k = 0; k < 50; k++)
{
objData[i].data_val3[k] = 20.00;
}
objData[i].data_val2 = 0.00;
}
cfun_call(objData,10); //Making call to C dll function
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} ", objData[i].data_val2);
Console.WriteLine("");//new line
Console.ReadLine();
}
}
这里从C#函数传递的值(objData)没有使用C dll函数更新,我不知道为什么。 有人能指出我正确的方向吗?
编辑1:
我按照建议更新了代码,
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct data
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public char[] data_val1;
public float data_val2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
public float[] data_val3;
};
初始化的struct元素,如下所示,
data[] objData = new data[10];
for (int i = 0; i < 10; i++)
{
//Fill the data in objitemData
objData[i] = new objData();
for (int j = 0; j < 100; j++)
{
objData[i].data_val1[j] = '\0'; //I am getting exception here
}
for (int k = 0; k < 50; k++)
{
objData[i].data_val3[k] = 20.00;
}
objData[i].data_val2 = 0.00;
}
运行时我得到null ptr异常,比如
未处理的类型&#39; System.NullReferenceException&#39;发生在mybinary.exe
附加信息:未将对象引用设置为对象的实例。
如何在manged代码中正确初始化struct数组元素?
编辑2:
还有一个问题,当我添加时,objData [i] .data_val3 [k] = randomData; // randomvalues,在使用contnt值进行cfun_call时没有更新它更新为什么?
答案 0 :(得分:3)
您对结构的翻译不正确。你需要它是这样的:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct data
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public char[] data_val1;
public float data_val2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
public float[] data_val3;
};
您必须将此结构化为结构,因为您需要传递值数组。使用类的声明会导致您传递一系列引用。
您现在需要显式初始化数组。这可能是这样的:
data[] objData = new data[10];
for (int i = 0; i < 10; i++)
{
objData[i].data_val1 = new char[100];
objData[i].data_val2 = 0.00;
objData[i].data_val3 = new float[50];
for (int k = 0; k < 50; k++)
{
objData[i].data_val3[k] = 20.0f;
}
}
此外,C ++ long
是32位宽,但C#long
是64位宽。因此你有一个不匹配。你的p / invoke应该是:
[DllImport("mycdll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void cfun_call(
[In, Out] data[] ouputItem_data,
int count
);