C#调用 C++的 dll 动态链接库

本文通过实例介绍如何在 c#中调用 C++编写的 dll。

1 首先用 C++编写一个测试用的 dll

1.1 新建一个 Win32 控制台工程

Drawing

1.2 Application settings 中将应用类型设置为 DLL

Drawing

1.3 在.cpp 文件中输入代码

#include "stdafx.h"
#include <stdio.h>
#include <string>
using namespace std;

extern "C"
{
struct foo{
int var1;
int var2;
unsigned char s[32];
unsigned char r[32];
double var3;
char arr[16];
};

__declspec(dllexport) int __stdcall DisplayHelloFromDLL(){
printf("Hello from DLL\n");
return 12345;
}

__declspec(dllexport) void __stdcall OutputStructValues(foo f){
printf("\nEntering OutputStruct\n");
printf("Size of struct is %d\n", sizeof(foo));
printf("var1 = %d\n", f.var1);
printf("var2 = %d\n", f.var2);
printf("%s\n", f.s);
printf("%s\n", f.r);
printf("var2 = %10f\n", f.var3);
printf("arr = %s\n", f.arr[2]);
printf("Exiting OutputStruct\n\n");
}

__declspec(dllexport) void __stdcall TestArrayInOut(int * in, int * out, int nSize) {
printf("\nEntering Array In out\n");
for (int i = 0; i < nSize; i++)
{
//*(out + i) = *(in + i);//这样写竟然不行!在 c#中调用出错了
out[i] = in[i] * 10;
}
}

关键的语句是:extern "C" __declspec(dllexport) void __stdcall

如果没有 __stdcall, 程序依然可以执行,但是调试时会报错。

2 C#中新建控制台程序,对 dll 进行测试

2.1 C#代码

using System;
using System.Runtime.InteropServices;

namespace cpp_dll_link
{
unsafe class Program
{
[DllImport("DllTest.dll")]
public static extern void DisplayHelloFromDLL();

[DllImport("DllTest.dll")]
public static extern void OutputStructValues(foo f);

[DllImport("DllTest.dll")]
public static extern void TestArrayInOut(IntPtr pin,IntPtr pout, int nSize);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct foo
{
public int inta;
public int intb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string z;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string x;
public Double doub;
public fixed byte arr[16];
}

static void Main(string[] args)
{

Console.WriteLine("This is C# program");
foo f;
f.inta = 10;
f.intb = 20;
f.z = "string1string1string1string1string1string1string1string1string1";
f.x = "string2";
f.doub = 5.67;
//f.arr = new byte[16];
for (int i = 0; i < 16; i++)
{
f.arr[i] = (byte)(i + 97);
}
DisplayHelloFromDLL();

int[] a = { 0, 1, 2, 3 };
int[] b = { 0, 0, 0, 0 };
int size = Marshal.SizeOf(a[0]) * a.Length;
//Console.WriteLine("size: %d", size);
IntPtr pa = Marshal.AllocHGlobal(16);
IntPtr pb = Marshal.AllocHGlobal(16);
Marshal.Copy(a, 0, pa, 4);
Marshal.Copy(b, 0, pb, 4);
TestArrayInOut(pa, pb, 4);
for (int i = 0; i < 4; i++)
Console.WriteLine(*((int *)pb + i));

OutputStructValues(f);
Console.WriteLine("End of app");
Console.ReadKey();
}
}
}

2.2 将 C++生成的 Dll 文件拷贝至 C#工程的调试目录下,然后就可以运行了

2.3 运行结果

Drawing

Date: <2016-09-22 四 17:30>

Author: ziyuan

Created: 2016-09-22 四 17:13

Emacs 25.1.50.1 (Org mode 8.2.10)

Validate

热评文章