VS2017中 C# dll引用(C生成dll,C++生成dll)小结

dll引用小结

一、dll与应用程序

动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件夹,你会发现文件夹中有很多DLL文件,Windows就是将一些主要的系统功能以DLL模块的形式实现。
动态链接库是不能直接执行的,也不能接收消息,它只是一个独立的文件,其中包含能被程序或其它DLL调用来完成一定操作的函数(方法。注:C#中一般称为“方法”),但这些函数不是执行程序本身的一部分,而是根据进程的需要按需载入,此时才能发挥作用。
DLL只有在应用程序需要时才被系统加载到进程的虚拟空间中,成为调用进程的一部分,此时该DLL也只能被该进程的线程访问,它的句柄可以被调用进程所使用,而调用进程的句柄也可以被该DLL所使用。在内存中,一个DLL只有一个实例,且它的编制与具体的编程语言和编译器都没有关系,所以可以通过DLL来实现混合语言编程。DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。
下面列出了当程序使用 DLL 时提供的一些优点:[1]

  1. 使用较少的资源
    当多个程序使用同一个函数库时,DLL 可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大大影响其他在 Windows 操作系统上运行的程序。
  2. 推广模块式体系结构
    DLL 有助于促进模块式程序的开发。这可以帮助您开发要求提供多个语言版本的大型程序或要求具有模块式体系结构的程序。模块式程序的一个示例是具有多个可以在运行时动态加载的模块的计帐程序。
  3. 简化部署和安装
    当 DLL 中的函数需要更新或修复时,部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外,如果多个程序使用同一个 DLL,那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复的第三方 DLL 时,此问题可能会更频繁地出现。

二、Dll的调用

每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍。首先,您需要了解什么是托管,什么是非托管。一般可以认为:非托管代码主要是基于win 32平台开发的DLL,activeX的组件,托管代码是基于.net平台开发的。如果您想深入了解托管与非托管的关系与区别,及它们的运行机制,请您自行查找资料,本文件在此不作讨论。

调用DLL非托管函数的一般方法

首先,应该在C#语言源程序中声明外部方法,其基本形式是:
[DLLImport(“DLL文件”)]
修饰符 extern 返回变量类型 方法名称 (参数列表)
其中:
DLL文件:包含定义外部方法的库文件。
修饰符: 访问修饰符,除了abstract以外在声明方法时可以使用的修饰符。
返回变量类型:在DLL文件中你需调用方法的返回变量类型。
方法名称:在DLL文件中你需调用方法的名称。
参数列表:在DLL文件中你需调用方法的列表。
注意:需要在程序声明中使用System.Runtime.InteropServices命名空间。
DllImport只能放置在方法声明上。
DLL文件必须位于程序当前目录或系统定义的查询路径中(即:系统环境变量中Path所设置的路径)。
返回变量类型、方法名称、参数列表一定要与DLL文件中的定义相一致。
若要使用其它函数名,可以使用EntryPoint属性设置,如:
[DllImport("user32.dll", EntryPoint="MessageBoxA")]
static extern int MsgBox(int hWnd, string msg, string caption, int type);
其它可选的 DllImportAttribute 属性:
CharSet 指示用在入口点中的字符集,如:CharSet=CharSet.Ansi;
SetLastError 指示方法是否保留 Win32"上一错误",如:SetLastError=true;
ExactSpelling 指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配,如:ExactSpelling=false;
PreserveSig指示方法的签名应当被保留还是被转换, 如:PreserveSig=true;
CallingConvention指示入口点的调用约定, 如:CallingConvention=CallingConvention.Winapi;
C#例子:
1.启动VS.NET,新建一个项目,项目名称为“import1”,模板为“控制台应用程序”。
代码如下

namespace import1
{
  class Program
  {
    [DllImport("user32.dll", EntryPoint = "MessageBoxA")]
    static extern int MsgBox(int hWnd, string msg, string caption, int type);
    static void Main(string[] args)
    {
        MsgBox(0, " 这就是用 DllImport 调用 DLL 弹出的提示框哦! ", " 挑战杯 ", 0x30);
    }
  }
}

然后运行即可
image.png

生成一个自定义的C语言dll

所用平台VisualStudio 2017
新建C++空项目
右键项目--->属性--->选择配置类型为动态库


image.png

在头文件和源文件下分别建立test.h和test.c
test.h

__declspec(dllexport) int sum(int a, int b);

test.c


//test.c
#include "test.h"
#include <stdio.h>

int sum(int a, int b) {
    return a + b;
}

生成项目,在相应的Debug文件夹下可以找到EasyHelloWorlddll.dll
找不到可以用listary搜索。
然后把该dll拷贝到C#项目文件的exe文件夹内(点击生成之后的Debug或者release文件夹)。

C# Vs中使用C的Dll

新建C#控制台程序ConsoleAppTestDllImport
Program.cs代码如下

using System;

namespace ConsoleAppTestDllImport
{
    using System.Runtime.InteropServices;

    class Program
    {
        [DllImport("EasyHelloWorlddll", EntryPoint = "sum", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Sum(int a, int b);

        static void Main(string[] args)
        {

            Console.WriteLine(Sum(2,3));
            Console.ReadKey();
        }
}

其中 EntryPoint="sum"是定义入口函数名,使用这个可以自行在下面修改函数名称,不使用则必须与C中的函数名相同。
这里注意[DllImport("EasyHelloWorlddll", EntryPoint = "sum", CallingConvention = CallingConvention.Cdecl)]
如果调用不加CallingConvertion,容易出现错误

image.png

详细见:https://blog.csdn.net/wjeson/article/details/8263335

C++生成Dll

这里只是介绍最简单的生成方法,以后学多了考虑出个合集
同上C建立新工程,只有代码不同


image.png

C++ test.h

#pragma once //头文件只编译一次
extern "C" __declspec(dllexport) int __stdcall sum(int n1, int n2);

test.cpp

//test.cpp
#include "test.h"
#include <stdio.h>

int __stdcall sum(int a, int b) 
{
    return a + b;
}

C#上调用也是一样的

{
    using System;
    using System.Runtime.InteropServices;
    class Program
    {
        [DllImport("EasyHelloWorlddll", EntryPoint = "sum")]
        public static extern int Sum(int a, int b);

        static void Main(string[] args)
        {
            Console.WriteLine(Sum(2,3));
            Console.ReadKey();
        }
}

关于32位和64位DLL

因为新版的Unity不支持32位框架dll的导入,于是需要创建64位dll,
创建方式,把之前的改为64位,同时把属性中的exe换为dll。可行

C++ 调用 C++

生成 myfish.h

#pragma once
extern "C" __declspec(dllexport) double __stdcall sum(double delta, double freq, double phase);

生成 myfish.cpp

#include "psm.h"
#include <stdio.h>
#include <math.h>

double __stdcall sum(double delta,double freq ,double phase) {
    double res =  100f * sin(delta+freq+ phase ) ;
    return res;
}

生成看情况,正常可以x64 Release

生成myfish.dll

新建项目aaa.sln

属性->VC++ 目录->包含目录,包含.h的目录

属性->VC++ 目录->库目录,包含.lib的目录

链接器->输入->附加依赖项->添加myfish.lib

#include <iostream>
#include "myfish.h"
int main()
{
    std::cout << "Sum" << sum(7, 8, 0);
    std::cout << "Hello World!\n";
    system("pause");
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342