怎么用Visual Studio把自己写的代码封装成动态库给别人使用

前面已经实现了用类封装自己实现的格式转换功能,现在怎么把自己的功能打包好让别人方便用呢?本文学习了怎么用Visual Studio来进行封装打包。

一、动态链接库模板

Visual Studio提供了动态链接库模板,咱们新建项目,选择模板就行,非常方便

新建完得到四个这样的文件,用它给的文件怕出什么问题,咱们自己新建几个文件写自己的代码。

二、头文件定义

头文件是最关键的地方,让其他人直接通过我们的头文件来访问我们的代码,这里就是接口处了。头文件要尽量简单,把类的定义丢上来就差不多了,其他的我们在cpp文件里再实现。而且头文件里除了系统库不要再去include其他自己定义的库啥的了,不然别人用的时候找不到include的东西。

//MyTranscoder.h
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <string>

#ifdef MYTRANSCODER_EXPORTS
#define MYTRANSCODER_API __declspec(dllexport)
#else
#define MYTRANSCODER_API __declspec(dllimport)
#endif

class MyTranscoderImpl;

class MYTRANSCODER_API NoCopyable
{
protected:
	NoCopyable() = default;
	virtual ~NoCopyable() = default;
	NoCopyable(NoCopyable const& other) = delete;
	NoCopyable& operator=(NoCopyable const& other) = delete;
	NoCopyable(NoCopyable&& other) = delete;
	NoCopyable& operator=(NoCopyable&& other) = delete;
};

class MYTRANSCODER_API MyTranscoder : public NoCopyable {
public:
	MyTranscoder();

	~MyTranscoder() override;

	bool transCode();

private:
	MyTranscoderImpl* fImpl;
};

这里还有一个很关键的地方,我们用的是动态库dll编译,要想得到静态库lib就得加上导出标志MYTRANSCODER_API。另外,在工程设置里面,属性-->C/C++-->预处理器-->预处理器定义,把MYTRANSCODER_EXPORTS宏定义加进去就可以了。

为了让头文件更加简洁,我们这里的MyTranscoder类只是单纯的做一个接口,我们再额外实现一个MyTranscoderImpl类来进行功能的实现.

MyTranscoderImpl.h文件就随便include啥文件进来都没关系了,反正别人使用的时候不需要管除了接口头文件其他的东西,我们直接把要用到的ffmpeg的库全在这里引入进来。

//MyTranscoderImpl.h
#pragma once
#include <string>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
#include <thread>
#include <mutex>
#include <condition_variable>
#include "SCOPEG.h"
#include <queue>
//此处添加与当前类声名相关的额外头文件

class MyTranscoderImpl {
public:
	MyTranscoderImpl();

	~MyTranscoderImpl();
	
	bool formatConver();
private:
	void decodeThread1();
	void encodeThread1();
    //解码参数包结构体
    struct DecodeParamPacket {
        std::string inputFile;
        AVFormatContext* inputFormatContext;
        AVStream* audioStream;
        int videoStreamIndex;
        int audioStreamIndex;
        AVStream* videoStream;
    };
    //编码参数包结构体
    struct EncodeParamPacket {
        std::string outputFileName;
        std::string format;
        AVStream* audioStream;
        AVStream* videoStream;
    };
    DecodeParamPacket fDecodeParam;
    EncodeParamPacket fEncodeParam;
    queue<AVFrame*> fFrameQueue;//帧队列
    std::mutex fMtx;  // 互斥量,保证线程访问的互斥
    std::condition_variable fCv;  // 条件变量,用于线程之间的通信
    int fRet = 0;
    bool fEnd = false;//全局结束标志
};

三、对应的功能实现cpp文件

首先MyTranscoder.h对应的MyTranscoder.cpp这里只是写个接口,所以cpp文件也就随便写点就行

//MyTranscoder.cpp
#include "pch.h"
#include "MyTranscoderImpl.h"
#include "../include/MyTranscoder.h"


MyTranscoder::MyTranscoder() {
	fImpl = new MyTranscoderImpl();
}

MyTranscoder::~MyTranscoder() {
	delete fImpl;
}

bool MyTranscoder::transCode() {
	return fImpl->formatConver();
}



然后是MyTranscoderImpl.cpp,把我们之前写的解码编码所有功能都往这里放。

#include "pch.h"
#include "MyTranscoderImpl.h"
//此处添加与当前类实现相关的额外头文件


MyTranscoderImpl::MyTranscoderImpl() {

}

MyTranscoderImpl::~MyTranscoderImpl() {

}


bool MyTranscoderImpl::formatConver()
{
    std::string inputFileName, outputFileName, format;
    std::cout << "请输入输入文件名(带后缀):";
    std::cin >> inputFileName;
    std::cout << "请输入输出格式(avi,mp4,wmv,mkv,flv...):";
    std::cin >> format;
    std::cout << "请输入输出文件名(带后缀):";
    std::cin >> outputFileName;
    /*inputFilename = "cartoonTrim.mp4";
    Format = "avi";
    outputFilename = "Multithreading.avi";*/
    fDecodeParam.inputFile = inputFileName;
    fEncodeParam.outputFileName = outputFileName;
    fEncodeParam.format = format;

    avformat_network_init(); // 初始化网络库
    AVStream* audioStream = nullptr;
    AVFormatContext* inputFormatContext = nullptr;
    AVStream* videoStream = nullptr;
    // 打开输入文件
    if (avformat_open_input(&inputFormatContext, fDecodeParam.inputFile.c_str(), nullptr, nullptr) != 0) {
        std::cout << "无法打开输入文件" << std::endl;
        return false;
    }
    ON_SCOPE_EXIT{ avformat_close_input(&inputFormatContext); };
    // 获取流信息
    if (avformat_find_stream_info(inputFormatContext, nullptr) < 0) {
        std::cout << "无法获取输入文件流信息" << std::endl;
        return false;
    }
    // 查找视频流和音频流索引
    int videoStreamIndex = -1;
    int audioStreamIndex = -1;
    for (int i = 0; i < inputFormatContext->nb_streams; i++) {
        if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
        }
        else if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audioStreamIndex = i;
        }
    }
    if (videoStreamIndex == -1 || audioStreamIndex == -1) {
        std::cout << "没有找到视频流" << std::endl;
        return false;
    }
    // 获取音频流,共享输入音频参数给音频编码器
    audioStream = inputFormatContext->streams[audioStreamIndex];
    videoStream = inputFormatContext->streams[videoStreamIndex];

    fDecodeParam.inputFormatContext = inputFormatContext;
    fDecodeParam.audioStream = audioStream;
    fDecodeParam.videoStreamIndex = videoStreamIndex;
    fDecodeParam.audioStreamIndex = audioStreamIndex;
    fDecodeParam.videoStream = videoStream;

    fEncodeParam.audioStream = audioStream;
    fEncodeParam.videoStream = videoStream;
    //解码线程
    std::thread decodeThr(&MyTranscoderImpl::decodeThread1,this);
    //编码线程
    std::thread encodeThr(&MyTranscoderImpl::encodeThread1,this);
    decodeThr.join();
    encodeThr.join();
    return true;
}
//解码线程
void MyTranscoderImpl::decodeThread1() {
    AVCodecContext* videoCodecContext = nullptr;
    AVCodecContext* audioCodecContext = nullptr;
    // 分配帧对象
    AVFrame* videoFrame = av_frame_alloc();
    AVFrame* audioFrame = av_frame_alloc();
    AVPacket* inputPacket = av_packet_alloc();
    ON_SCOPE_EXIT{ av_frame_free(&videoFrame); };
    ON_SCOPE_EXIT{ av_frame_free(&audioFrame); };
    ON_SCOPE_EXIT{ av_packet_free(&inputPacket); };
    if (!videoFrame || !audioFrame || !inputPacket) {
        std::cout << "分配帧对象失败" << std::endl;
        return;
    }

    // 获取视频解码器
    const AVCodec* videoCodec = avcodec_find_decoder(fDecodeParam.videoStream->codecpar->codec_id);
    if (!videoCodec) {
        std::cout << "没有找到视频解码器" << std::endl;
        return;
    }

    // 创建并打开视频解码器上下文
    videoCodecContext = avcodec_alloc_context3(videoCodec);
    if (!videoCodecContext) {
        std::cout << "创建视频解码器上下文失败" << std::endl;
        return;
    }
    ON_SCOPE_EXIT{ avcodec_free_context(&videoCodecContext); };
    //视频流参数去填充上下文context
    avcodec_parameters_to_context(videoCodecContext, fDecodeParam.videoStream->codecpar);
    if (avcodec_open2(videoCodecContext, videoCodec, nullptr) < 0) {
        std::cout << "打开视频解码器失败" << std::endl;
        return;
    }

    // 获取音频编码器
    const AVCodec* audioCodec = avcodec_find_decoder(fDecodeParam.audioStream->codecpar->codec_id);
    if (!audioCodec) {
        std::cout << "获取音频编码器失败" << std::endl;
        return;
    }
    // 创建并打开音频解码器上下文
    audioCodecContext = avcodec_alloc_context3(audioCodec);
    if (!audioCodecContext) {
        std::cout << "创建音频编码器上下文失败" << std::endl;
        return;
    }
    ON_SCOPE_EXIT{ avcodec_free_context(&audioCodecContext); };

    //音频流参数填充上下文
    avcodec_parameters_to_context(audioCodecContext, fDecodeParam.audioStream->codecpar);
    if (avcodec_open2(audioCodecContext, audioCodec, nullptr) < 0) {
        std::cout << "打开音频编码器失败" << std::endl;
        return;
    }
    //打印输入信息
    av_dump_format(fDecodeParam.inputFormatContext, 0, fDecodeParam.inputFile.c_str(), 0);

    //解码
    while (av_read_frame(fDecodeParam.inputFormatContext, inputPacket) >= 0) {
        if (inputPacket->stream_index == fDecodeParam.videoStreamIndex) {
            fRet = avcodec_send_packet(videoCodecContext, inputPacket);
            if (fRet < 0) {
                break;
            }
            while (fRet >= 0) {
                fRet = avcodec_receive_frame(videoCodecContext, videoFrame);
                if (fRet == AVERROR(EAGAIN) || fRet == AVERROR_EOF) {
                    break;
                }
                else if (fRet < 0) {
                    std::cout << "视频解码 ret 异常" << std::endl;
                    return;
                }
                //传输帧到队列中,新建一个AVFrame_变量,避免每帧使用相同的地址
                videoFrame->quality = 1;//音视频标志
                AVFrame* videoFrame_ = av_frame_clone(videoFrame);
                //如果帧队列大于等于50就等待唤醒
                unique_lock<mutex> lock2(fMtx);
                while (fFrameQueue.size() >= 50)
                    fCv.wait(lock2);
                //将帧推入队列
                fFrameQueue.push(videoFrame_);
                //推入队列后,唤醒编码线程
                fCv.notify_one();
                break;
            }
            av_packet_unref(inputPacket);
        }
        else if (inputPacket->stream_index == fDecodeParam.audioStreamIndex) {
            // 音频流处理
            fRet = avcodec_send_packet(audioCodecContext, inputPacket);
            if (fRet < 0) {
                break;
            }
            while (fRet >= 0) {
                fRet = avcodec_receive_frame(audioCodecContext, audioFrame);
                if (fRet == AVERROR(EAGAIN) || fRet == AVERROR_EOF) {
                    break;
                }
                else if (fRet < 0) {
                    std::cout << "音频解码 ret 异常" << std::endl;
                    return;
                }
                //传输帧到队列中,新建一个AVFrame变量
                AVFrame* audioFrame_ = av_frame_clone(audioFrame);
                //如果帧队列大于等于50就等待唤醒
                unique_lock<mutex> lock2(fMtx);
                while (fFrameQueue.size() >= 50)
                    fCv.wait(lock2);
                fFrameQueue.push(audioFrame_);
                //唤醒编码线程
               fCv.notify_one();
                break;
            }
            av_packet_unref(inputPacket);
        }
    }
    //解码完成后,唤醒最后一次
    fCv.notify_one();
    //设置结束全局变量,通知编码线程结束
    fMtx.lock();
    fEnd = true;
    fMtx.unlock();
}
//编码线程
void MyTranscoderImpl::encodeThread1()
{
    AVFormatContext* outputFormatContext = nullptr;
    SwsContext* swsContext = nullptr;
    AVCodecID videoCodecId;
    AVCodecID audioCodecId;
    AVPacket* videoOutputPacket = av_packet_alloc();
    AVPacket* audioOutputPacket = av_packet_alloc();
    ON_SCOPE_EXIT{ av_packet_free(&videoOutputPacket); };
    ON_SCOPE_EXIT{ av_packet_free(&audioOutputPacket); };
    if (!videoOutputPacket || !audioOutputPacket) {
        std::cout << "分配帧对象失败" << std::endl;
        return;
    }
    {   //编解码器控制
        if (fEncodeParam.format == "avi")
        {
            videoCodecId = AV_CODEC_ID_MPEG2VIDEO;
            audioCodecId = AV_CODEC_ID_PCM_S16LE;
        }
        else if (fEncodeParam.format == "mp4")
        {
            videoCodecId = AV_CODEC_ID_H264;
            audioCodecId = AV_CODEC_ID_AAC;
        }
        else if (fEncodeParam.format == "wmv")
        {
            videoCodecId = AV_CODEC_ID_MSMPEG4V3;
            audioCodecId = AV_CODEC_ID_WMAV2;
        }
        else if (fEncodeParam.format == "mkv")
        {
            videoCodecId = AV_CODEC_ID_H264;
            audioCodecId = AV_CODEC_ID_MP3;
        }
        else if (fEncodeParam.format == "flv")
        {
            videoCodecId = AV_CODEC_ID_H264;
            audioCodecId = AV_CODEC_ID_AAC;
        }
        else {
            std::cout << "不支持转换为这种格式" << std::endl;
            return;
        }
    }
    // 创建输出文件的上下文
    avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, fEncodeParam.outputFileName.c_str());
    if (!outputFormatContext) {
        std::cout << "创建输出文件的上下文失败" << std::endl;
        return;
    }
    ON_SCOPE_EXIT{ avformat_free_context(outputFormatContext); };

    // 添加视频流到输出上下文
    AVStream* outVideoStream = avformat_new_stream(outputFormatContext, nullptr);
    if (!outVideoStream) {
        std::cout << "添加视频流到输出文件失败" << std::endl;
        return;
    }
    outVideoStream->id = outputFormatContext->nb_streams - 1;
    avcodec_parameters_copy(outVideoStream->codecpar, fEncodeParam.videoStream->codecpar);
    outVideoStream->codecpar->codec_tag = 0;

    // 设置视频编码器
    const AVCodec* outVideoCodec = avcodec_find_encoder(videoCodecId);
    if (!outVideoCodec) {
        std::cout << "设置视频编码器失败" << std::endl;
        return;
    }
    AVCodecContext* outVideoCodecContext = avcodec_alloc_context3(outVideoCodec);
    if (!outVideoCodecContext) {
        std::cout << "设置视频编码器上下文失败" << std::endl;
        return;
    }
    ON_SCOPE_EXIT{ avcodec_free_context(&outVideoCodecContext); };
    //视频编码器参数设置
    {
        //avcodec_parameters_to_context(outVideoCodecContext, outVideoStream->codecpar);
        outVideoCodecContext->codec_id = videoCodecId;
        outVideoCodecContext->time_base.den = 25;
        outVideoCodecContext->time_base.num = 1;
        outVideoCodecContext->gop_size = 13;
        outVideoCodecContext->bit_rate = 8000000;
        outVideoCodecContext->refs = 0;
        outVideoCodecContext->max_b_frames = 10;
        outVideoCodecContext->width = 1920;
        outVideoCodecContext->height = 1080;
        outVideoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
    }
    //从输出上下文中复制参数到输出流
    avcodec_parameters_from_context(outVideoStream->codecpar, outVideoCodecContext);


    // 打开视频编码器
    if (avcodec_open2(outVideoCodecContext, outVideoCodec, nullptr) < 0) {
        std::cout << "无法打开视频编码器" << std::endl;
        return;
    }

    // 添加音频流到输出文件
    AVStream* outAudioStream = avformat_new_stream(outputFormatContext, nullptr);
    if (!outAudioStream) {
        std::cout << "添加音频流到输出文件失败" << std::endl;
        return;
    }

    outAudioStream->id = outputFormatContext->nb_streams - 1;
    //输出音频流参数复制
    avcodec_parameters_copy(outAudioStream->codecpar, fEncodeParam.audioStream->codecpar);
    outAudioStream->time_base.den = 11025;
    outAudioStream->time_base.num = 256;
    outAudioStream->codecpar->bit_rate = 320018;
    outAudioStream->codecpar->profile = 1;
    outAudioStream->codecpar->sample_rate = 44100;
    outAudioStream->codecpar->frame_size = 1024;
    av_channel_layout_default(&outAudioStream->codecpar->ch_layout, 2);
    //outAudioStream->codecpar->ch_layout.nb_channels = 2;
    outAudioStream->codecpar->codec_tag = 0;
    //outAudioStream->codecpar->ch_layout.order = AV_CHANNEL_ORDER_NATIVE;
    //outAudioStream->codecpar->ch_layout.u.mask = 0x03;
    //outAudioStream->codecpar->channels = 1;

    // 设置音频编码器
    const AVCodec* outAudioCodec = avcodec_find_encoder(audioCodecId);
    if (!outAudioCodec) {
        std::cout << "设置音频编码器失败" << std::endl;
        return;
    }
    AVCodecContext* outAudioCodecContext = avcodec_alloc_context3(outAudioCodec);
    if (!outAudioCodecContext) {
        std::cout << "设置音频编码器上下文失败" << std::endl;
        return;
    }
    ON_SCOPE_EXIT{ avcodec_free_context(&outAudioCodecContext); };
    //音频编码器参数
    avcodec_parameters_to_context(outAudioCodecContext, outAudioStream->codecpar);
    outAudioCodecContext->codec_id = audioCodecId;
    outAudioCodecContext->time_base = fEncodeParam.audioStream->time_base;
    //outAudioCodecContext->time_base.den = 51111100;
    //outAudioCodecContext->time_base.num = 1;
    //outAudioCodecContext->sample_rate = 43110;
    outAudioCodecContext->sample_fmt = AV_SAMPLE_FMT_S16;
    //av_channel_layout_default(&outAudioCodecContext->ch_layout, 2);
    avcodec_parameters_from_context(outAudioStream->codecpar, outAudioCodecContext);
    if (fEncodeParam.format == "flv")
    {
        outAudioCodecContext->sample_fmt = AV_SAMPLE_FMT_FLTP;
        av_channel_layout_default(&outAudioCodecContext->ch_layout, 3);

    }
    // 打开音频编码器
    if (avcodec_open2(outAudioCodecContext, outAudioCodec, nullptr) < 0) {
        std::cout << "无法打开音频编码器" << std::endl;
        return;
    }

    // 打开输出文件
    if (!(outputFormatContext->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&outputFormatContext->pb, fEncodeParam.outputFileName.c_str(), AVIO_FLAG_WRITE) < 0) {
            std::cout << "无法打开输出文件" << std::endl;
            return;
        }
    }

    // 写入输出文件头
    if (avformat_write_header(outputFormatContext, nullptr) < 0) {
        std::cout << "无法写入输出文件头" << std::endl;
        return;
    }
    //打印输出相关信息
    av_dump_format(outputFormatContext, 0, fEncodeParam.outputFileName.c_str(), 1);
    int nVideoCount = 0;
    int nAudioCount = 0;
    bool queueSizeLess = 0;
    bool queueIsEmpty = 0;
    //开始编码
    while (1)
    {
        //等待解码唤醒
        unique_lock<mutex> lock1(fMtx);
        while (fFrameQueue.empty())
            fCv.wait(lock1);
        AVFrame* frame = fFrameQueue.front();
        fFrameQueue.pop();
        lock1.unlock();
        //编码
        {
            if (frame->quality == 1) {
                // 编码视频帧
                frame->pts = (int64_t)(40 * (nVideoCount) / av_q2d(outVideoCodecContext->time_base) / 1000.0);//时间
                nVideoCount++;
                fRet = avcodec_send_frame(outVideoCodecContext, frame);
                if (fRet < 0) {
                    break;
                }
                while (fRet >= 0) {
                    fRet = avcodec_receive_packet(outVideoCodecContext, videoOutputPacket);
                    if (fRet == AVERROR(EAGAIN) || fRet == AVERROR_EOF) {
                        break;
                    }
                    else if (fRet < 0) {
                        std::cout << "视频编码 ret 异常" << std::endl;
                        return;
                    }

                    av_packet_rescale_ts(videoOutputPacket, outVideoCodecContext->time_base, outVideoStream->time_base);
                    videoOutputPacket->stream_index = outVideoStream->index;

                    // 写入视频帧到输出文件
                    fRet = av_interleaved_write_frame(outputFormatContext, videoOutputPacket);
                    if (fRet < 0) {
                        break;
                    }
                }
            }
            else {
                // 编码音频帧
                //Frame->pts = (int64_t)( (nAudioCount) / av_q2d(outAudioCodecContext->time_base) / 44100.0);//时间
                frame->pts = nAudioCount * 1024;
                nAudioCount++;
                fRet = avcodec_send_frame(outAudioCodecContext, frame);
                if (fRet < 0) {
                    break;
                }

                while (fRet >= 0) {
                    fRet = avcodec_receive_packet(outAudioCodecContext, audioOutputPacket);
                    if (fRet == AVERROR(EAGAIN) || fRet == AVERROR_EOF) {
                        break;
                    }
                    else if (fRet < 0) {
                        std::cout << "音频编码 ret 异常" << std::endl;
                        return;
                    }

                    av_packet_rescale_ts(audioOutputPacket, outAudioCodecContext->time_base, outAudioStream->time_base);
                    audioOutputPacket->stream_index = outAudioStream->index;

                    // 写入音频帧到输出文件
                    fRet = av_interleaved_write_frame(outputFormatContext, audioOutputPacket);
                    if (fRet < 0) {
                        break;
                    }
                }
            }
            //释放每次新建的AVFrame
            av_frame_free(&frame);
            //如果队列帧数量已经少于50就唤醒解码继续工作
            fMtx.lock();
            queueSizeLess = fFrameQueue.size() < 50 ? 1 : 0;
            queueIsEmpty = fFrameQueue.empty() ? 1 : 0;
            fMtx.unlock();
            if (queueSizeLess)
                fCv.notify_one();
        }
        //结束整个编码线程
        if (fEnd && queueIsEmpty) { break; }
    }
    // 写入输出文件尾部
    av_write_trailer(outputFormatContext);
}

四、生成库

右击我们的项目名,再点击生成,就OK了,在下面这个目录会得到下面这四个文件。

五、其他人引用

其他人用我们的代码只需要头文件和lib库文件就可以了,新建一个项目模拟一下别人使用我们的代码。头文件比较简单直接把.h文件下载好然后include进来进行。

#include <iostream>
#include "../include/MyTranscoder.h"

int main()
{
    
    clock_t start, end;
    start = clock();
    MyTranscoder transCoder;
    if (!transCoder.transCode()) {
        std::cout << "Failed to convert!" << std::endl;
        return -1;
    }
    std::cout << "Conversion complete!" << std::endl;
    end = clock();
    std::cout << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << std::endl;
    return 0;
	
}

库文件需要简单配置一下

属性--链接器--常规--附加库目录:然后把刚刚那个lib文件的路径放上去

属性--链接器--输入--附加依赖项:把MyTranscoder.lib库丢进去

这样就差不多OK了,初学者,记录记录学习过程。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的 Visual Studio 2022 封装示例: 1. 创建一个新的 C++ 普通 Win32 控制台应用程序项目。 2. 在“解决方案资源管理器”中,右键单击“项目”并选择“添加”->“新建项”。 3. 选择“C++ 文件(.cpp)”并命名为“mylib.cpp”。 4. 在“mylib.cpp”文件中,编一个简单的函数: ``` #include "stdafx.h" #include "mylib.h" int add(int a, int b) { return a + b; } ``` 5. 在“解决方案资源管理器”中右键单击“Header Files”文件夹并选择“添加”->“新建项”。 6.选择“头文件(.h)”并命名为“mylib.h”。 7. 在“mylib.h”文件中,声明函数: ``` #pragma once int add(int a, int b); ``` 8. 在“解决方案资源管理器”中,右键单击“项目”并选择“属性”。 9. 选择“配置属性”->“常规”->“目标名称”,将其改为“mylib”。 10. 选择“配置属性”->“常规”->“目标扩展名”,将其改为“.lib”。 11. 选择“配置属性”->“C/C++”->“常规”,将“附加包含目录”设置为“$(ProjectDir)”。 12. 选择“配置属性”->“C/C++”->“输出文件”,将“生程序数据”设置为“否”。 13. 选择“配置属性”->“链接器”->“常规”,将“生 map 文件”设置为“否”。 14. 选择“配置属性”->“链接器”->“输入”,添加“kernel32.lib”到“附加依赖项”。 15. 在“解决方案资源管理器”中,右键单击“mylib”项目并选择“生”。 现在,你的封装已经生。你可以在其他应用程序中使用它,只需在该应用程序中包含“mylib.h”头文件并链接到“mylib.lib”即可。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值