飞道的博客

VS2017下创建C++动态库导出符合并完成调用测试(DLL可供C#调用)

473人阅读  评论(0)

一、环境介绍

VS版本:  VS2017

编程语言: C++

二、功能介绍

使用VS2017项目模板创建C++动态库生成工程,生成动态库。然后再创建一个C++工程调用动态库完成测试。

三、创建动态库

 工程创建之后,VS会自动生成一个示例模板;下面截图里是将VS自动生成的模板代码给删除掉了,添加自己编写了2个测试函数。


  
  1. #ifdef DLLLIBRARY_EXPORTS
  2. #define DLLLIBRARY_API __declspec(dllexport)
  3. #else
  4. #define DLLLIBRARY_API __declspec(dllimport)
  5. #endif
  6. EXTERN_C DLLLIBRARY_API char* Version(void);
  7. EXTERN_C DLLLIBRARY_API int sum(int a, int b);


  
  1. static char version_str[] = "v20210524";
  2. // 获取版本号
  3. DLLLIBRARY_API char* Version(void)
  4. {
  5. return version_str;
  6. }
  7. // 求和
  8. DLLLIBRARY_API int sum(int a, int b)
  9. {
  10. int c = a + b;
  11. return c;
  12. }

写好之后,编译生成动态库。

生成的库文件在解决方案目录下:

四、创建C++工程调用动态库

将第一步生成的库文件xxx.lib拷贝到当前测试工程目录下:

编写调用库的测试代码:


  
  1. #include <iostream>
  2. #pragma comment(lib, "DLLLIBRARY.lib")
  3. extern "C"
  4. {
  5. extern __declspec(dllexport) char* Version(void);
  6. extern __declspec(dllexport) int sum(int a, int b);
  7. };
  8. using namespace std;
  9. int main()
  10. {
  11. int c = sum( 12, 34);
  12. cout << "求和:" << c << endl;
  13. char *p = Version();
  14. cout << "版本号:" << p;
  15. }

写完代码后,直接编译运行,会报错提示缺少xxx.dll,接下来把xxx.dll拷贝到程序运行目录下即可。

拷贝xxx.dll到程序运行目录下: 

再次编译运行:

五、C#调用动态库测试

创建一个C#控制台工程,准备调用DLL库测试。

编写调用库的测试代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Runtime.InteropServices;
  7. namespace ConsoleApp1
  8. {
  9. class Program
  10. {
  11. [ DllImport("DLLLIBRARY.dll", EntryPoint = "sum", CallingConvention = CallingConvention.Cdecl)]
  12. extern static int sum(int a, int b);
  13. [ DllImport("DLLLIBRARY.dll", EntryPoint = "Version",CharSet =CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  14. extern static IntPtr Version();
  15. static void Main(string[] args)
  16. {
  17. Console.WriteLine(sum( 100, 200));
  18. Console.WriteLine(Marshal.PtrToStringAnsi(Version()));
  19. Console.ReadKey();
  20. }
  21. }
  22. }

编译运行,提示无法加载xxx.dll,接下来将xxx.dll拷贝到程序运行目录下即可。

拷贝xxx.dll到当前程序运行目录下: 

再次运行:

六、C#传入C指针字符串参数

如果C的函数需要传入字符串,C#可以这样传递:

C函数原型:


  
  1. static char version_str[] = "v20210524";
  2. //获取版本号
  3. ECRSTOOLLIBRARY_API char* Version( void)
  4. {
  5. return version_str;
  6. }
  7. void GetApplicationDirPath(char * buff)
  8. {
  9. printf( "传入的参数:%s\n", buff);
  10. }

C#代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Runtime.InteropServices;
  7. namespace CSharp_LoadLibrary
  8. {
  9. class Program
  10. {
  11. [ DllImport("ECRSTOOLLIBRARY.dll", EntryPoint = "Version", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  12. extern static IntPtr Version();
  13. [ DllImport("ECRSTOOLLIBRARY.dll", EntryPoint = "GetApplicationDirPath", CallingConvention = CallingConvention.Cdecl)]
  14. extern static void GetApplicationDirPath(IntPtr text);
  15. static void Main(string[] args)
  16. {
  17. //申请空间
  18. IntPtr pBuff = Marshal.AllocHGlobal( 100);
  19. //将string转为IntPtr类型
  20. string str = "我是传递给C++的字符串";
  21. pBuff = Marshal.StringToHGlobalAnsi(str);
  22. //调用C++方法
  23. GetApplicationDirPath(pBuff);
  24. //释放空间
  25. Marshal.FreeHGlobal(pBuff);
  26. Console.WriteLine(Marshal.PtrToStringAnsi(Version()));
  27. Console.ReadKey();
  28. }
  29. }
  30. }

 

 

 


转载:https://blog.csdn.net/xiaolong1126626497/article/details/117223128
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场