VS 2017 创建并使用动态库保姆教程+Netcdf环境配置

最近在利用VS 2017 调用Netcdf的c语言代码处理CERES数据集时,在安装完cdf软件时,需要用VS2017调用系统文件下的include\bin\lib的文件时,碰到了一些动态库的问题,花了挺久时间才整好,今天分享给大家:

1.动态库的创建

 1)首先利用VS2017 建立两个空项目,第一个为test项目,第二个为动态库项目;此处需要将项目的属性分别设置为.exe 和.dll; 

2)在动态库项目——Danamic_ex中建立.h 和.c 文件;在.h中编写如下相应代码:

#ifndef _DANAMIC_DLL_H
#define _DANAMIC_DLL_H


#ifdef _DLL_API
     #define DANAMIC_DLL_API  __declspec(dllexport)
#else
     #define DANAMIC_DLL_API  __declspec(dllimport)
#endif // _DLL_API


#ifdef __cplusplus
extern "C" {
#endif // _cplusplus
	
	DANAMIC_DLL_API int Add_z(int a, int b);

	DANAMIC_DLL_API int Sub_z(int a, int b);

	DANAMIC_DLL_API void print_z(void);


#ifdef __cplusplus
}
#endif // _cplusplus

#ifndef _DANAMIC_DLL_H

#define _DANAMIC_DLL_H

代码段

#endif // !_DANAMIC_DLL_H

            ---上述代码目的:为了避免重复定义而添加一个预定义:

#ifdef _DLL_API  

     #define DANAMIC_DLL_API  __declspec(dllexport)

#else

     #define DANAMIC_DLL_API  __declspec(dllimport)

#endif // _DLL_API

//----VS中自己的一个预定义,避免在生成文件中和调用文件中出现dllexport和dllimport的不同

//另外需要注意的一个问题就是,__declspec(dllexport)的前边应该是两个下划线

#ifdef __cplusplus

extern "C" {

#endif // _cplusplus

代码。。。。

#ifdef __cplusplus

}

#endif // _cplusplus

 //这段代码是为了适应c/c++的编译环境,__cplusplus在c++编译器中定义为非零值;当使用c编译器编译时,__cplusplus的值为0值,不需要编译,直接运行代码;当使用c++编译时,__cplusplus的值为非零值,所以extern “C”{}存在,强制要求c++编译器按照c语言的风格编译;

在Danamic_dll.c中为了测试方便,编写如下代码:

#include "Danamic_dll.h"
#include<stdio.h>
DANAMIC_DLL_API int Add_z(int a, int b)
{
	return a+b;
}

DANAMIC_DLL_API int Sub_z(int a, int b)
{
	return a-b;
}

DANAMIC_DLL_API void print_z(void)
{
	printf("\nOK!\n");
}

3)生成建立动态连链接库,会生成.dll、.lib、.pdb等文件,如下图其中的.dll和.lib为我们所需要的文件;这里的.lib 文件不同于静态库中的.lib文件,其中不包含函数的代码,只是包含一些辅助信息,建立其.dll 和.h的联系;

动态库的生成也可以使用.def 文件来设置,这种方式可以保证生成动态库中函数入口的名称不变; 

2.动态库的使用 

   为了验证动态库的使用,以及后边Netcdf的配置方便,这里给出使用方法:

1)第一种使用方法,与调用静态库一样,见本人的另一篇文章,这里给出头文件的写法,其主要是通过路径来调用,但是要注意一定要保持.dll文件和.exe 保持在同一个文件夹下才可以; 

2)使用项目的属性设置来配置,将.lib、.h的路径包含在其中:其设置如下:

c/c++头文件.h添加: 

c/c++的.lib添加: 

上述设置完成后,也一定要保持.dll文件和.exe 保持在同一个文件夹下才可以,这个行为可以通过自己手动复制粘贴,或更改动态库生成的保存文件;

由于本文档是为了说明动态库的使用,以便后边在VS2017 中调用netcdf 中的使用,因此对于动态库的入口函数DLLmain没有整理,以及动态的动态加载和释放没有整理;

2、VS 2017 +Netcdf环境配置

Netcdf可以在NetCDF: The NetCDF-C Tutorial中下载,netcdfnetCDF Downloads (官方地址)

在c盘中安装后,如下图

其中bin中为.dll文件,include中为.h文件,lib中为.lib文件;

新建一个空文件:

环境配置
项目属性\VC++目录\包含目录 添加 C:\Program Files (x86)\netCDF 4.6.1\include (安装位置的include目录)


项目属性\VC++目录\库目录 添加 C:\Program Files (x86)\netCDF 4.6.1\lib (安装位置的lib目录)



项目属性\链接器\输入\附加依赖项 添加 netcdf.lib

 

测试代码如下:

#include <stdlib.h>
 #include <stdio.h>
 #include <netcdf.h>
  
 /* This is the name of the data file we will create. */
 #define FILE_NAME "simple_xy.nc"
  
 /* We are writing 2D data, a 6 x 12 grid. */
 #define NDIMS 2
 #define NX 6
 #define NY 12
  
 /* Handle errors by printing an error message and exiting with a
  * non-zero status. */
 #define ERRCODE 2
 #define ERR(e) {printf("Error: %s\n", nc_strerror(e)); exit(ERRCODE);}
  
 int
 main()
 {
    /* When we create netCDF variables and dimensions, we get back an
     * ID for each one. */
    int ncid, x_dimid, y_dimid, varid;
    int dimids[NDIMS];
  
    /* This is the data array we will write. It will be filled with a
     * progression of numbers for this example. */
    int data_out[NX][NY];
  
    /* Loop indexes, and error handling. */
    int x, y, retval;
  
    /* Create some pretend data. If this wasn't an example program, we
     * would have some real data to write, for example, model
     * output. */
    for (x = 0; x < NX; x++)
       for (y = 0; y < NY; y++)
      data_out[x][y] = x * NY + y;
  
    /* Always check the return code of every netCDF function call. In
     * this example program, any retval which is not equal to NC_NOERR
     * (0) will cause the program to print an error message and exit
     * with a non-zero return code. */
  
    /* Create the file. The NC_CLOBBER parameter tells netCDF to
     * overwrite this file, if it already exists.*/
    if ((retval = nc_create(FILE_NAME, NC_CLOBBER, &ncid)))
       ERR(retval);
  
    /* Define the dimensions. NetCDF will hand back an ID for each. */
    if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid)))
       ERR(retval);
    if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid)))
       ERR(retval);
  
    /* The dimids array is used to pass the IDs of the dimensions of
     * the variable. */
    dimids[0] = x_dimid;
    dimids[1] = y_dimid;
  
    /* Define the variable. The type of the variable in this case is
     * NC_INT (4-byte integer). */
    if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS,
                 dimids, &varid)))
       ERR(retval);
  
    /* End define mode. This tells netCDF we are done defining
     * metadata. */
    if ((retval = nc_enddef(ncid)))
       ERR(retval);
  
    /* Write the pretend data to the file. Although netCDF supports
     * reading and writing subsets of data, in this case we write all
     * the data in one operation. */
    if ((retval = nc_put_var_int(ncid, varid, &data_out[0][0])))
       ERR(retval);
  
    /* Close the file. This frees up any internal netCDF resources
     * associated with the file, and flushes any buffers. */
    if ((retval = nc_close(ncid)))
       ERR(retval);
  
    printf("*** SUCCESS writing example file simple_xy.nc!\n");
	system("pause");
    return 0;
 }

运行结果:

大功告成,一切顺利!

以上供大家学习!

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值