锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C#调用C++的DLL问题和C#调用C++的DLL原理描述
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

C#调用C++的DLL问题和C#调用C++的DLL原理描述

近期项目里使用到了此技术,研究后有几个心得和大家分享一二,本文描述了2个调用问题和一些原理的英语翻译,希望大家有所收获。

PInvoke 签名与非托管的目标签名不匹配

问题如下图:

PInvoke签名与非托管的目标签名不匹配

使用的import语句如下:

[DllImport("authdll.dll")]
private static extern int KeyPass(StringBuilder key, StringBuilder pass);

经过研究,修改如下,还是没有解决:

[DllImport("authdll.dll",EntryPoint="#1")]
private static extern int KeyPass(StringBuilder key, StringBuilder pass);
再改如下,PInvoke不匹配问题解决了,但是函数执行后,参数获取的值不对:

[DllImport("authdll.dll",EntryPoint="#1", CallingConvention = CallingConvention.Cdecl)]
private static extern int KeyPass(StringBuilder key, StringBuilder pass);
参数问题就是下面问题了。

char *参数在C#里的转换和正确获取值

经研究char*参数对应StringBuilder,调用语句如下:

StringBuilder slkey = new StringBuilder(), slpass = new StringBuilder();
int ireturn = KeyPass(slkey, slpass);

执行后变量里为空,没有值。把import语句修改如下,字符串变量里有值了:

[DllImport("authdll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int KeyPass(StringBuilder key, StringBuilder pass);
这里去掉EntryPoint只是乱试,并没觉得它会是个问题,因为#1入口是通过depends查看dll后是对应的,不会有问题。去掉后可以获取值,只能用实践证明理论,EntryPoint对调用参数有影响。

对函数调用后效果评估后发现和C++的效果不一样,结果字符串的长度不一样,这就更奇怪了,没办法,只有再试着想是不是StringBuilder的空间长度有影响,试着把调用修改如下:

StringBuilder slkey = new StringBuilder(256), slpass = new StringBuilder(256);
int ireturn = KeyPass(slkey, slpass);

在构造函数里,加上长度,扩大内部空间,参数得到的字符串长度正确了。

codeproject上的理论翻译

After spending some time trying to implement this simple task, I started to search similar code examples over the Internet. I was really very surprised when found that all examples were slightly different from what I needed. Finally, I realized that there is no (at least spending 30 min in the net) easy-to-use example, that’s why I decided to write this article.通过互联网找不到满意的例子,所以自己写个。

Assuming that you already know what a DLL is, let's begin with creating a simple one.假设熟悉DLL。

  1. Start Visual Studio .NET. 打开VS。
  2. Go to File->New->Project.新建项目
  3. Select Visual C++ Project, and from the “Templates”, select “Win32 Project”. 选择VC++项目,模板选择Win32。
  4. Give the name to your project. This will be the name of your final DLL (in my case: TestLib). 项目命名,DLL文件的名称会和项目名一样。
  5. Press OK.
  6. Select DLL from “Application Type” (“Application Settings” tab). 应用类型选择DLL
  7. Check “Empty Project” (we need to create our project from scratch, right?), and press Finish. 空白项目

OK, now we should attach an empty source file to our blank project.

  1. Start Solution Explorer (if it’s not displayed). 打开解决方案视图
  2. Right click to the “Source Files”, Add->Add New Item then select “C++ File” and give the name to it. 添加新C++文件。
  3. Press “Open”. 打开

In the opened window, enter the following code:输入如下代码

#include <stdio.h>    extern "C"  {    __declspec(dllexport) void DisplayHelloFromDLL()    {      printf ("Hello from DLL !\n");    }  }

Please note that __declspec(dllexport) is an obligatory prefix which makes DLL functions available from an external application.__declspec(dllexport)是必须的前缀,它使DLL函数面向外部的项目可用。

extern “C” (with brackets) is also very important, it shows that all code within brackets is available from “outside”. Although code will compile even without this statement, during runtime, you’ll get a very unpleasant error. So, do not forget to include it.

Build this application and your DLL will be ready-to-use.

Now it’s time to create an application which will use our DLL, as the main title explains. We will create this type of application using Microsoft’s C#.

Creating a simple C# application:C#应用

  1. Start Visual Studio .NET.
  2. Go to File->New->Project.
  3. Select Visual C# Project. From the “Templates”, you can either select “Console Application”, or an “Empty Project” just like it was described above.
  4. Give the name to your application.
  5. Press OK.

Into the specified class, insert the following two lines:

[DllImport("TestLib.dll")]    public static extern void DisplayHelloFromDLL ();

In C#, keyword extern indicates that the method is implemented externally.extern表示方法在外部实现。

Your code should look something like this:

using System;  using System.Runtime.InteropServices;     // DLL support    class HelloWorld  {      [DllImport("TestLib.dll")]      public static extern void DisplayHelloFromDLL ();        static void Main ()      {          Console.WriteLine ("This is C# program");          DisplayHelloFromDLL ();      }  }

Please, note that System.Runtime.InteropServices is required for operations with the DLL.注意 System.Runtime.InteropServices是强制需要的。

According to MSDN:

“The System.Runtime.InteropServices namespace provides a collection of classes useful for accessing COM objects, and native APIs from .NET”它提供集合类用于存取COM对象,和本地API

OK, now build this application, and then copy the previously built DLL into the Debug/Release directory of the current application. The DLL should be in the same directory as your main application.

Now start an application. If everything you’ve made was correct, you should get something like this:拷贝dll文件到C#项目的debug/release目录来测试。

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内