Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(1)

编译好的版本放到了这里,包括静态库和动态库。大家直接用吧。
http://download.csdn.net/detail/liyuanbhu/9618257

Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(1)

以前一直都是用 MINGW 来编译 GSL 的,这样编译出来的 GSL 可以在 VS2013 及以下版本的 Visual Stdio 中使用。但是最近升级 Visual Stdio 到 Visual Stdio 2015 就发现问题了。编译应用程序时会报错误,提示有几个 external symbol 找不到。

之所以会报这个错误,是因为 VS2015 更新了 C 标准库的内部实现,与旧版本的 Visual Stdio 不兼容了。而 MinGW 的 C 标准库只是与 VS2013 兼容的。要是等 MinGW 更新到与 VS2015 兼容不知要到猴年马月了。

*说实话,我认为 GSL 的设计也有些问题,作为一个数值计算库,应该不依赖除标准数学库之外的其他 C 库的。 GSL 用到 fprintf 输出错误信息纯粹多此一举,要知道还有不少计算环境(比如单片机、DSP 一类的)根本就不支持文件系统,自然也没有 fprintf 函数。在这些不具备 C 标准库的环境中移植 GSL 就会遇到各种问题。
*

没办法,我的项目中需要用到 GSL ,那就只能自己动手编译一个能用在 VS2015 中的 GSL 了。

考虑到以后升级和维护的方便性,我没用 VS2015 的 IDE,而是用了 Qt Creator。 因为 Qt Creator 的项目文件就是个简单的文本文件,便于我以后在里面增加、删除东西。 虽然用了 Qt Creator,但是这个项目和 Qt 没任何关系的。

我曾经写过一篇文章:Visual Stdio 环境下使用 GSL (GNU Scientific Library)
http://blog.csdn.net/liyuanbhu/article/details/47685377

介绍如何用 MinGW2 编译 GSL 。虽然和现在的场景不一样,但是也有很多可以借鉴的地方。

使用的 gsl 的版本为 2.1。

生成 gslcblas.lib

建立一个新目录:gslcblas 作为我们项目路径。下面的子目录如下:

gslcblas-staticlib
--include
----gsl
--source
----cblas

刚开始这些目录当时都是空的。
头文件放在 gslcblas/include/gsl 中。
源代码放到 gslcblas/source/cblas 中。

下面这些文件从 gsl-2.1 的源码目录中拷贝到 gslcblas/include/gsl 目录中。

gsl_cblas.h
gsl_machine.h
gsl_minmax.h
gsl_pow_int.h
gsl_sys.h
gsl_inline.h
gsl_math.h
gsl_nan.h
gsl_precision.h
gsl_types.h

config.h 文件拷贝到 gslcblas/include 目录中。 这个文件的生成方法可以参考我的上篇博客:
Visual Stdio 环境下使用 GSL (GNU Scientific Library)
http://blog.csdn.net/liyuanbhu/article/details/47685377

这里给一个适用于 VS2015 的 config.h。注意这个 config.h 只适用于 vs2015,不适用于低版本的 vs。

/* config.h.  Generated from config.h.in by configure.  */
/* config.h.in.  Generated from configure.ac by autoheader.  */

/* Disable deprecated functions and enums while building */
#define GSL_DISABLE_DEPRECATED 1

/* Define if you have inline with C99 behavior */
//#define HAVE_C99_INLINE
#undef HAVE_C99_INLINE
/* Define to 1 if you have the declaration of `acosh', and to 0 if you don't.
   */
#define HAVE_DECL_ACOSH 1

/* Define to 1 if you have the declaration of `asinh', and to 0 if you don't.
   */
#define HAVE_DECL_ASINH 1

/* Define to 1 if you have the declaration of `atanh', and to 0 if you don't.
   */
#define HAVE_DECL_ATANH 1

/* Define to 1 if you have the declaration of `expm1', and to 0 if you don't.
   */
#undef HAVE_DECL_EXPM1
//#define HAVE_DECL_EXPM1 0

/* Define to 1 if you have the declaration of `feenableexcept', and to 0 if
   you don't. */
#define HAVE_DECL_FEENABLEEXCEPT 0

/* Define to 1 if you have the declaration of `fesettrapenable', and to 0 if
   you don't. */
#define HAVE_DECL_FESETTRAPENABLE 0

/* Define to 1 if you have the declaration of `finite', and to 0 if you don't.
   */
#define HAVE_DECL_FINITE 0

/* Define to 1 if you have the declaration of `fprnd_t', and to 0 if you
   don't. */
#define HAVE_DECL_FPRND_T 0

/* Define to 1 if you have the declaration of `frexp', and to 0 if you don't.
   */
#define HAVE_DECL_FREXP 1

/* Define to 1 if you have the declaration of `hypot', and to 0 if you don't.
   */
#define HAVE_DECL_HYPOT 1

/* Define to 1 if you have the declaration of `isfinite', and to 0 if you
   don't. */
#define HAVE_DECL_ISFINITE 1

/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
   */
#define HAVE_DECL_ISINF 1

/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
   */
#define HAVE_DECL_ISNAN 1

/* Define to 1 if you have the declaration of `ldexp', and to 0 if you don't.
   */
#define HAVE_DECL_LDEXP 1

/* Define to 1 if you have the declaration of `log1p', and to 0 if you don't.
   */
#define HAVE_DECL_LOG1P 1

/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */

/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */

/* Defined if you have ansi EXIT_SUCCESS and EXIT_FAILURE in stdlib.h */
#define HAVE_EXIT_SUCCESS_AND_FAILURE 1

/* Defined on architectures with excess floating-point precision */
#define HAVE_EXTENDED_PRECISION_REGISTERS 1

/* Define if x86 processor has sse extensions. */
#define HAVE_FPU_X86_SSE
/* #undef HAVE_FPU_X86_SSE */

/* Define to 1 if you have the <ieeefp.h> header file. */
#define HAVE_IEEEFP_H 0

/* Define this if IEEE comparisons work correctly (e.g. NaN != NaN) */
#define HAVE_IEEE_COMPARISONS 1

/* Define this if IEEE denormalized numbers are available */
#define HAVE_IEEE_DENORMALS 0

/* Define if you have inline */
//#define HAVE_INLINE 1
#undef HAVE_INLINE

/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1

/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 0

/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1

/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1

/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1

/* Define this if printf can handle %Lf for long double */
#define HAVE_PRINTF_LONGDOUBLE 1
/* #undef HAVE_PRINTF_LONGDOUBLE */

/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1

/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1

/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 0

/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the `strtol' function. */
#define HAVE_STRTOL 1

/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1

/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 0

/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 0

/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 0

/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1

/* Define if you need to hide the static definitions of inline functions */
/* #undef HIDE_INLINE_STATIC */

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#define LT_OBJDIR ".libs/"

/* Name of package */
#define PACKAGE "gsl"

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""

/* Define to the full name of this package. */
#define PACKAGE_NAME "gsl"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "gsl 2.1"

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gsl"

/* Define to the home page for this package. */
#define PACKAGE_URL ""

/* Define to the version of this package. */
#define PACKAGE_VERSION "2.1"

/* Defined if this is an official release */
#define RELEASED /**/

/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

/* Version number of package */
#define VERSION "2.1"

/* Define to 1 if type `char' is unsigned and you are not using gcc.  */
#ifndef __CHAR_UNSIGNED__
/* # undef __CHAR_UNSIGNED__ */
#endif

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
    #undef inline
#endif

/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

/* Define to empty if the keyword `volatile' does not work. Warning: valid
   code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */

/* Use 0 and 1 for EXIT_SUCCESS and EXIT_FAILURE if we don't have them */
#if !HAVE_EXIT_SUCCESS_AND_FAILURE
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif

/* Define one of these if you have a known IEEE arithmetic interface */
/* #undef HAVE_GNUSPARC_IEEE_INTERFACE */
/* #undef HAVE_GNUM68K_IEEE_INTERFACE */
/* #undef HAVE_GNUPPC_IEEE_INTERFACE */
/* #undef HAVE_GNUX86_IEEE_INTERFACE */
/* #undef HAVE_SUNOS4_IEEE_INTERFACE */
/* #undef HAVE_SOLARIS_IEEE_INTERFACE */
/* #undef HAVE_HPUX11_IEEE_INTERFACE */
/* #undef HAVE_HPUX_IEEE_INTERFACE */
/* #undef HAVE_TRU64_IEEE_INTERFACE */
/* #undef HAVE_IRIX_IEEE_INTERFACE */
/* #undef HAVE_AIX_IEEE_INTERFACE */
/* #undef HAVE_FREEBSD_IEEE_INTERFACE */
/* #undef HAVE_OS2EMX_IEEE_INTERFACE */
/* #undef HAVE_NETBSD_IEEE_INTERFACE */
/* #undef HAVE_OPENBSD_IEEE_INTERFACE */
/* #undef HAVE_DARWIN_IEEE_INTERFACE */
/* #undef HAVE_DARWIN86_IEEE_INTERFACE */

/* Define a rounding function which moves extended precision values
   out of registers and rounds them to double-precision. This should
   be used *sparingly*, in places where it is necessary to keep
   double-precision rounding for critical expressions while running in
   extended precision. For example, the following code should ensure
   exact equality, even when extended precision registers are in use,

      double q = GSL_COERCE_DBL(3.0/7.0) ;
      if (q == GSL_COERCE_DBL(3.0/7.0)) { ... } ;

   It carries a penalty even when the program is running in double
   precision mode unless you compile a separate version of the
   library with HAVE_EXTENDED_PRECISION_REGISTERS turned off. */

#if HAVE_EXTENDED_PRECISION_REGISTERS
#define GSL_COERCE_DBL(x) (gsl_coerce_double(x))
#else
#define GSL_COERCE_DBL(x) (x)
#endif

/* Substitute gsl functions for missing system functions */

#if !HAVE_DECL_HYPOT
#define hypot gsl_hypot
#endif

#if !HAVE_DECL_LOG1P
#define log1p gsl_log1p
#endif

#if !HAVE_DECL_EXPM1
#define expm1 gsl_expm1
#endif

#if !HAVE_DECL_ACOSH
#define acosh gsl_acosh
#endif

#if !HAVE_DECL_ASINH
#define asinh gsl_asinh
#endif

#if !HAVE_DECL_ATANH
#define atanh gsl_atanh
#endif

#if !HAVE_DECL_LDEXP
#define ldexp gsl_ldexp
#endif

#if !HAVE_DECL_FREXP
#define frexp gsl_frexp
#endif

#if !HAVE_DECL_ISINF
#define isinf gsl_isinf
#endif

#if !HAVE_DECL_ISFINITE
#define isfinite gsl_finite
#endif

#if !HAVE_DECL_FINITE
#define finite gsl_finite
#endif

#if !HAVE_DECL_ISNAN
#define isnan gsl_isnan
#endif

#ifdef __GNUC__
#define DISCARD_POINTER(p) do { ; } while(p ? 0 : 0);
#else
#define DISCARD_POINTER(p) /* ignoring discarded pointer */
#endif

#if defined(GSL_RANGE_CHECK_OFF) || !defined(GSL_RANGE_CHECK)
#define GSL_RANGE_CHECK 0  /* turn off range checking by default internally */
#endif

#define RETURN_IF_NULL(x) if (!x) { return ; }

这里 gsl_inline.h 需要做些修改。里面有这么一段:

#ifdef HAVE_INLINE
#  if defined(__GNUC_STDC_INLINE__) || defined(GSL_C99_INLINE) || defined(HAVE_C99_INLINE)
#    define INLINE_DECL inline  /* use C99 inline */
#    define INLINE_FUN inline
#  else
#    define INLINE_DECL         /* use GNU extern inline */
#    define INLINE_FUN extern inline
#  endif
#else
#  define INLINE_DECL /* */
#endif

更改为:

#ifdef HAVE_INLINE
#  if defined(__GNUC_STDC_INLINE__) || defined(GSL_C99_INLINE) || defined(HAVE_C99_INLINE)
#    define INLINE_DECL inline  /* use C99 inline */
#    define INLINE_FUN inline
#  else
#    define INLINE_DECL         /* use Visual C++ __inline */
#    define INLINE_FUN __inline
#  endif
#else
#  define INLINE_DECL /* */
#endif

然后将 gsl-2.1/cblas 目录中的所有文件都拷贝到 gslcblas/source/cblas 中。下面就是一个个的把源代码文件添加到项目中了。最后的项目文件如下:

#-------------------------------------------------
#
# Project created by QtCreator 2016-08-23T19:14:13
#
#-------------------------------------------------

QT       -= core gui

TARGET = gslcblas
TEMPLATE = lib
CONFIG += staticlib

SOURCES += \
    source/cblas/caxpy.c \
    source/cblas/ccopy.c \
    source/cblas/cdotc_sub.c \
    source/cblas/cdotu_sub.c \
    source/cblas/cgbmv.c \
    source/cblas/cgemm.c \
    source/cblas/cgemv.c \
    source/cblas/cgerc.c \
    source/cblas/cgeru.c \
    source/cblas/chbmv.c \
    source/cblas/chemm.c \
    source/cblas/chemv.c \
    source/cblas/cher.c \
    source/cblas/cher2.c \
    source/cblas/cher2k.c \
    source/cblas/cherk.c \
    source/cblas/chpmv.c \
    source/cblas/chpr.c \
    source/cblas/chpr2.c \
    source/cblas/cscal.c \
    source/cblas/csscal.c \
    source/cblas/cswap.c \
    source/cblas/csymm.c \
    source/cblas/csyr2k.c \
    source/cblas/csyrk.c \
    source/cblas/ctbmv.c \
    source/cblas/ctbsv.c \
    source/cblas/ctpmv.c \
    source/cblas/ctpsv.c \
    source/cblas/ctrmm.c \
    source/cblas/ctrmv.c \
    source/cblas/ctrsm.c \
    source/cblas/ctrsv.c \
    source/cblas/dasum.c \
    source/cblas/daxpy.c \
    source/cblas/dcopy.c \
    source/cblas/ddot.c \
    source/cblas/dgbmv.c \
    source/cblas/dgemm.c \
    source/cblas/dgemv.c \
    source/cblas/dger.c \
    source/cblas/dnrm2.c \
    source/cblas/drot.c \
    source/cblas/drotg.c \
    source/cblas/drotm.c \
    source/cblas/drotmg.c \
    source/cblas/dsbmv.c \
    source/cblas/dscal.c \
    source/cblas/dsdot.c \
    source/cblas/dspmv.c \
    source/cblas/dspr.c \
    source/cblas/dspr2.c \
    source/cblas/dswap.c \
    source/cblas/dsymm.c \
    source/cblas/dsymv.c \
    source/cblas/dsyr.c \
    source/cblas/dsyr2.c \
    source/cblas/dsyr2k.c \
    source/cblas/dsyrk.c \
    source/cblas/dtbmv.c \
    source/cblas/dtbsv.c \
    source/cblas/dtpmv.c \
    source/cblas/dtpsv.c \
    source/cblas/dtrmm.c \
    source/cblas/dtrmv.c \
    source/cblas/dtrsm.c \
    source/cblas/dtrsv.c \
    source/cblas/dzasum.c \
    source/cblas/dznrm2.c \
    source/cblas/hypot.c \
    source/cblas/icamax.c \
    source/cblas/idamax.c \
    source/cblas/isamax.c \
    source/cblas/izamax.c \
    source/cblas/sasum.c \
    source/cblas/saxpy.c \
    source/cblas/scasum.c \
    source/cblas/scnrm2.c \
    source/cblas/scopy.c \
    source/cblas/sdot.c \
    source/cblas/sdsdot.c \
    source/cblas/sgbmv.c \
    source/cblas/sgemm.c \
    source/cblas/sgemv.c \
    source/cblas/sger.c \
    source/cblas/snrm2.c \
    source/cblas/srot.c \
    source/cblas/srotg.c \
    source/cblas/srotm.c \
    source/cblas/srotmg.c \
    source/cblas/ssbmv.c \
    source/cblas/sscal.c \
    source/cblas/sspmv.c \
    source/cblas/sspr.c \
    source/cblas/sspr2.c \
    source/cblas/sswap.c \
    source/cblas/ssymm.c \
    source/cblas/ssymv.c \
    source/cblas/ssyr.c \
    source/cblas/ssyr2.c \
    source/cblas/ssyr2k.c \
    source/cblas/ssyrk.c \
    source/cblas/stbmv.c \
    source/cblas/stbsv.c \
    source/cblas/stpmv.c \
    source/cblas/stpsv.c \
    source/cblas/strmm.c \
    source/cblas/strmv.c \
    source/cblas/strsm.c \
    source/cblas/strsv.c \
    source/cblas/xerbla.c \
    source/cblas/zaxpy.c \
    source/cblas/zcopy.c \
    source/cblas/zdotc_sub.c \
    source/cblas/zdotu_sub.c \
    source/cblas/zdscal.c \
    source/cblas/zgbmv.c \
    source/cblas/zgemm.c \
    source/cblas/zgemv.c \
    source/cblas/zgerc.c \
    source/cblas/zgeru.c \
    source/cblas/zhbmv.c \
    source/cblas/zhemm.c \
    source/cblas/zhemv.c \
    source/cblas/zher.c \
    source/cblas/zher2.c \
    source/cblas/zher2k.c \
    source/cblas/zherk.c \
    source/cblas/zhpmv.c \
    source/cblas/zhpr.c \
    source/cblas/zhpr2.c \
    source/cblas/zscal.c \
    source/cblas/zswap.c \
    source/cblas/zsymm.c \
    source/cblas/zsyr2k.c \
    source/cblas/zsyrk.c \
    source/cblas/ztbmv.c \
    source/cblas/ztbsv.c \
    source/cblas/ztpmv.c \
    source/cblas/ztpsv.c \
    source/cblas/ztrmm.c \
    source/cblas/ztrmv.c \
    source/cblas/ztrsm.c \
    source/cblas/ztrsv.c

HEADERS += \
    source/cblas/cblas.h
unix {
    target.path = /usr/lib
    INSTALLS += target
}


INCLUDEPATH += ./include/

编译之后就能得到 gslcblas.lib 文件了。编译时会报一些 warning。类似于:
warning: C4244: “=”: 从“double”转换到“float”,可能丢失数据

可以忽略这些错误,或者在报错的文件的开头加上:

#pragma warning (disable: 4244)

下面来生成动态库 gslcblas.lib 和 gslcblas.dll

生成动态库需要 gslcblas.def 文件。 gsl 本身没有提供这个文件。这里我来提供一个:

LIBRARY gslcblas
EXPORTS 

cblas_caxpy
cblas_ccopy
cblas_cdotc_sub
cblas_cdotu_sub
cblas_cgbmv
cblas_cgemm
cblas_cgemv
cblas_cgerc
cblas_cgeru
cblas_chbmv
cblas_chemm
cblas_chemv
cblas_cher
cblas_cher2
cblas_cher2k
cblas_cherk
cblas_chpmv
cblas_chpr
cblas_chpr2
cblas_cscal
cblas_csscal
cblas_cswap
cblas_csymm
cblas_csyr2k
cblas_csyrk
cblas_ctbmv
cblas_ctbsv
cblas_ctpmv
cblas_ctpsv
cblas_ctrmm
cblas_ctrmv
cblas_ctrsm
cblas_ctrsv
cblas_dasum
cblas_daxpy
cblas_dcopy
cblas_ddot
cblas_dgbmv
cblas_dgemm
cblas_dgemv
cblas_dger
cblas_dnrm2
cblas_drot
cblas_drotg
cblas_drotm
cblas_drotmg
cblas_dsbmv
cblas_dscal
cblas_dsdot
cblas_dspmv
cblas_dspr
cblas_dspr2
cblas_dswap
cblas_dsymm
cblas_dsymv
cblas_dsyr
cblas_dsyr2
cblas_dsyr2k
cblas_dsyrk
cblas_dtbmv
cblas_dtbsv
cblas_dtpmv
cblas_dtpsv
cblas_dtrmm
cblas_dtrmv
cblas_dtrsm
cblas_dtrsv
cblas_dzasum
cblas_dznrm2
cblas_icamax
cblas_idamax
cblas_isamax
cblas_izamax
cblas_sasum
cblas_saxpy
cblas_scasum
cblas_scnrm2
cblas_scopy
cblas_sdot
cblas_sdsdot
cblas_sgbmv
cblas_sgemm
cblas_sgemv
cblas_sger
cblas_snrm2
cblas_srot
cblas_srotg
cblas_srotm
cblas_srotmg
cblas_ssbmv
cblas_sscal
cblas_sspmv
cblas_sspr
cblas_sspr2
cblas_sswap
cblas_ssymm
cblas_ssymv
cblas_ssyr
cblas_ssyr2
cblas_ssyr2k
cblas_ssyrk
cblas_stbmv
cblas_stbsv
cblas_stpmv
cblas_stpsv
cblas_strmm
cblas_strmv
cblas_strsm
cblas_strsv
cblas_xerbla
cblas_zaxpy
cblas_zcopy
cblas_zdotc_sub
cblas_zdotu_sub
cblas_zdscal
cblas_zgbmv
cblas_zgemm
cblas_zgemv
cblas_zgerc
cblas_zgeru
cblas_zhbmv
cblas_zhemm
cblas_zhemv
cblas_zher
cblas_zher2
cblas_zher2k
cblas_zherk
cblas_zhpmv
cblas_zhpr
cblas_zhpr2
cblas_zscal
cblas_zswap
cblas_zsymm
cblas_zsyr2k
cblas_zsyrk
cblas_ztbmv
cblas_ztbsv
cblas_ztpmv
cblas_ztpsv
cblas_ztrmm
cblas_ztrmv
cblas_ztrsm
cblas_ztrsv

之后生成 gslcblas.dll 就很容易了。主要一行命令:

link /subsystem:windows /machine:x86 /DLL /def:gslcblas.def /out:dll\gslcblas.dll gslcblas.lib msvcrt.lib

这里之所以要链接 msvcrt.lib, 是因为 dll 文件需要有 Dll_Main 函数。可是gsl 没有提供这个函数,这时我们就借用 msvcrt 里面的同名函数了。

其实还有一种做法。我们可以自己提供一个 DllMain.c 文件:

#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
    return TRUE;
}

这个文件编译为 DllMain.obj 文件。之后修改一下我们的命令行:

link /subsystem:windows /machine:x86 /DLL /def:gslcblas.def /out:dll\gslcblas.dll gslcblas.lib DllMain.obj

就可以了。两种方法的效果是相同的。

至此,我们有了静态库文件: gslcblas.lib
和动态库文件: gslcblas.dll gslcblas.lib 和 gslcblas.exp

之后我们从 gsl 的文档里提取些测试代码,来测试我们的 dll 是否工作正常。下面的代码是 gsl ref 中的例子。如何在项目中使用 dll 就不多说了,这个非常简单,大家应该都会的。

#include <stdio.h>
#include <gsl/gsl_cblas.h>

int main(int argc, char *argv[])
{
    int lda = 3;
    float A[] = { 0.11, 0.12, 0.13, 0.21, 0.22, 0.23 };
    int ldb = 2;
    float B[] = { 1011, 1012, 1021, 1022, 1031, 1032 };
    int ldc = 2;
    float C[] = { 0.00, 0.00, 0.00, 0.00 };
    /* Compute C = A B */
    cblas_sgemm (CblasRowMajor, CblasNoTrans, CblasNoTrans, 2, 2, 3,
    1.0, A, lda, B, ldb, 0.0, C, ldc);
    printf ("[ %g, %g\n", C[0], C[1]);
    printf (" %g, %g ]\n", C[2], C[3]);
    return 0;
}

输出结果与文档上是一致的。说明我们生成的 dll 是可以工作的。

[ 367.76, 368.12
 674.06, 674.72 ]

先写这么多,明天介绍如何生成 gsl.dll 文件(这个工作量比较大,估计要写 4到5篇博客才能说明白)。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值