项目中需要通过c#调用c项目,为了安全方便起见对c项目打包供c#调用,其中c项目中包含较为复杂的结构体。
1.c封装dll
源文件:
#include "stdio.h"
#include "demo.h"
int __stdcall add(int a, int b) { return a + b; }
dbox __stdcall getbox(double a, double b) {
po p = {0.123, 0.456};
dbox db = {a / 2, b / 2, p};
return db;
}
头文件:
#ifndef TESTC_H
#define TESTC_H
#define TESTC_API __declspec(dllexport)
typedef struct po {
double x, y;
}po;
typedef struct dbox {
double dx, dy;
po dp;
} dbox;
#ifdef __cplusplus
extern "C" {
#endif
TESTC_API int __stdcall add(int a, int b);//__stdcall为调用方式,在调用时需保持一致
TESTC_API dbox __stdcall getbox(double a, double b);
#ifdef __cplusplus
}
#endif
#endif
2.C#调用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace csharp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("demo.dll", EntryPoint = "mult", ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
static extern int mult(int a, int b);
[StructLayout(LayoutKind.Sequential)]
public struct po
{
public double x;
public double y;
}
[StructLayout(LayoutKind.Sequential)]
public struct dbox
{
public double dx;
public double dy;
public po dp;
}
[DllImport("demo.dll", EntryPoint = "getbox", ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]//对应c封装的调用约定Std
static extern dbox getbox(double a, double b);
private void button1_Click(object sender, EventArgs e)
{
int te = mult(4, 5);
dbox box = getbox(0.2, 0.3);
double he = box.dp.x + box.dp.y;
MessageBox.Show(he.ToString());
}
}
}
其中在定义嵌套结构体时需提前定义基础结构体。