北京海淀财政局网站设计素材网站会员哪个最好

当前位置: 首页 > news >正文

北京海淀财政局网站,设计素材网站会员哪个最好,建网站什么框架,宁波建网站选哪家好一点资源文件 .rc 文件 会被 rc.exe 变成 .res 文件(二进制文件) 在链接时链接进入 .exe 文件 一、如何保护源码 程序编译链接过程 不想让别人拿到源代码#xff0c;但是想让其使用功能#xff0c;根据上图观察#xff0c;把自己生成的obj给对方#xff0c;对方拿到obj后…资源文件 .rc 文件 会被 rc.exe 变成 .res 文件(二进制文件) 在链接时链接进入 .exe 文件 一、如何保护源码 程序编译链接过程 不想让别人拿到源代码但是想让其使用功能根据上图观察把自己生成的obj给对方对方拿到obj后链接到自己的程序中。 新建一个控制台项目进行测试目录结构 Math.h Math.cpp test.cpp 编译后会生成一个 Math.obj的文件 再新建一个工程使用Math.obj 首先包含头文件其次需要导入 .obj文件 方式一直接托进解决方案里 方式二项目-属性-链接器-输入-附加依赖项-箭头-编辑-添加obj文件一行一个obj文件 项目目录结构 Math.h 如何兼容C test.c   链接时报错 原因 C语言的名称粉碎是_Sub_Add; C的名称粉碎是 ?SubYAHHHZ?AddYAHHHZ 编译器拿着“SubYAHHHZ”在obj中匹配C的_Sub当然匹配不上 解决办法告诉编译器名称粉碎的时候按照C的名称粉碎规则进行粉碎。 C 项目使用时函数声明加上extern C后C支持extern C语法能够直接使用 C项目使用时由于函数声明上extern C但是C不支持该语法不认识所以编译不通过 解决办法头文件被C 包含的时候前面不加extern C   int Add(int n1, int n2);                   头文件被C 包含的时候声明前面加上extern C 说明用C风格名称粉碎去找实现extern C 条件编译宏这样使用的时候就可以不管是C包含还是Cpp包含了 //要想C 和C 都能所用该obj声明的前面必须加上extern C生成的obj文件名称粉碎是C风格的。C可以使用C也可以使用 //C 项目使用时函数声明加上extern C后C支持extern C语法能够直接使用 //C 项目使用时由于函数声明上extern C但是C不支持该语法不认识所以编译不通过。//解决办法头文件被C 包含的时候前面不加extern C int Add(int n1, int n2); // 头文件被C 包含的时候声明前面加上extern C 说明用C风格名称粉碎去找实现extern C int Add(int n1, int n2);//条件编译宏这样使用的时候就可以不管是C包含还是Cpp包含了 #ifdef __cplusplus extern C { #endif // __cplusplusint Add(int n1, int n2);#ifdef __cplusplus } #endif // __cplusplus上述的obj的方法中当有很多obj时候需要拷贝很多的obj很不方便考虑将这些obj合并成一个大的“obj”这时就引出了静态库的概念。 补充 #pragma once 是一种预处理指令用于确保头文件只被编译一次。当一个头文件被多次包含在不同的源文件中时使用 #pragma once 可以防止重复包含从而避免编译错误和重复定义的问题。 #pragma once 的作用类似于传统的头文件保护宏header guard但更加简洁和方便。传统的头文件保护宏需要在头文件开头和结尾分别使用条件编译语句如 #ifndef HEADER_NAME_H、#define HEADER_NAME_H 和 #endif以确保头文件只被编译一次。而 #pragma once 只需要在头文件的开头使用一次即可达到相同的效果。 使用 #pragma once 的好处是可以提高编译速度因为编译器可以直接根据指令判断是否需要重新编译头文件。而传统的头文件保护宏需要进行条件判断会增加编译时间和额外的预处理工作。 二、静态库 动态库 概述 函数和数据被编译进一个二进制文件通常扩展名为.lib。在使用静态库的情况下在编译可执行文件时链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件.exe文件。 本质把所有的obj文件全部打包到一个.lib文件内。 缺点 维护困难如果.lib更新使用的工程如需更新则必须重新编译。磁盘冗余如果很多工程使用就要拷贝很多份.lib文件这些lib都是一样的无法很好的同时兼容C和C其他语言无法使用 动态链接库(DLL) 通常不能直接运行也不能接收信息只有在其他模块调用动态链接库中的函数时才能发挥作用。通常我们把完成某种功能的函数放在一个动态链接库中提供给其他程序调用。DLL就是整个windows操作系统的基础。动态链接库不能直接运行也不能接收消息。他们是一些独立的文件。 Windows API中所有的函数都包含在DLL中其中有3个重要的DLL Kernel32.dll包含用于管理内存、进程和线程的函数、例如CreateThread函数。User32.dll它包含用于执行用户界面任务如窗口的创建和消息的传送的函数。例如CreateWindow函数。GDI32.dll它包含用于画图和显示文本的函数。 使用动态链接库的好处 可以采用多种编程语言来编写。增强产品的功能扩展插件提供二次开发的平台扩展插件简化项目管理一个团队负责自己团队的dll可以节省磁盘空间和内存有助于资源的共享有助于实现应用程序的本地化。 三、静态链接库创建与使用 VS2019中直接找到静态链接库一路确认即可 不适用预编译头即可 项目目录 pch.h framework.h 文件是作用是减少重复文件编译提升性能有关。不用管 如果想建立一个自己的静态链接库直接添加 .h  .cpp文件即可编译后就可以得到 .lib 文件 使用静态库和使用 .obj 类似

  1. 添加头文件使用者才能知道传的什么参数以及其他 2. 拷贝lib文件和.h头文件到VS工程根目录 3. 添加lib文件到工程的方式用法   a. 直接拖入项目中   b. 依赖项添加.lib文件   c. 代码内添加.lib文件 # pragma commentlib,lib路径 如何把两个 obj 合成为 lib 静态库中还可以放 全局变量类(通过源文件右击添加-类) 四、动态链接库创建 新建类向导项目类型.dll动态链接库。 动态链接库中有导出函数和非导出函数 导出函数DLL提供给其他应用程序调用的函数非导出函数给DLL内的函数调用的函数中间函数等。 如果想导出函数给外面的工程使用需要指定函数告诉编译器哪个函数需要导出 从DLL中导出函数 为了让DLL导出一些函数需要在每一个将要被导出的函数前面添加标识符__declspec(dllexport)  编译生成DLL文件和LIB文件 LIB文件称为DLL的导入库文件是一个特殊的库文件和静态库文件有着本质上的区别引入库文件包含该DLL导出的函数和变量的符号名;而DLL文件包含该DLL实际函数和数据。 工程结构 CTest.h #pragma once class __declspec(dllexport) CTest { public:void Show(); }; Add.h #pragma once #ifdef __cplusplus extern C { #endif // cplusplusdeclspec(dllexport) int Add(int n1, int n2);__declspec(dllexport) extern int g_nVal; #ifdef __cplusplus } #endif // __cplusplus Sub.h #pragma once #ifdef __cplusplus extern C { #endif // cplusplusdeclspec(dllexport) int Sub(int n1, int n2); #ifdef __cplusplus } #endif // __cplusplusAdd.cpp #include Add.h int Add(int n1, int n2) {return n1 n2; } int g_nVal 0x12345678;CTest.cpp #include CTest.h #include iostream using namespace std; void CTest::Show() {cout CTest::Foo() endl; } dll.cpp #include iostream #include CTest.h #include Add.h #include Sub.h int main() {std::cout Add(1, 2) std::endl;std::cout Sub(2, 1) std::endl;CTest test;test.Show(); } Sub.cpp #include Sub.h int Sub(int n1, int n2) {return n1 - n2; }编译后生成以下文件 在下面动态链接库的debug目录下生成了dll文件dll.exp 文件是一个输出库文件。 LIB文件称为DLL的导入库文件是一个特殊的库文件和静态库文件有着本质上的区别引入库文件包含该DLL导出的函数和变量的符号名;而DLL文件包含该DLL实际函数和数据。 查看导出函数工具-DEPENDS拖进去使用即可 五、动态链接库的两种调用方式 动态链接库的使用 静态调用在程序编译的时候将DLL的信息植入可执行文件动态调用在程序中用语句显示地加载DLL编译器不需要知道任何关于DLL的信息。 显式加载和隐式加载是在使用动态链接库DLL时的两种加载方式。下面我将为你解释这两种加载方式的区别 隐式加载Implicit Loading 在编译时程序会将对 DLL 的引用嵌入到可执行文件中。在程序运行时操作系统会自动加载并初始化 DLL。隐式加载不需要手动加载 DLL 或指定 DLL 的路径。函数调用时直接使用函数名进行调用编译器会根据嵌入的引用找到对应的函数地址。DLL 的导入函数表会在程序加载时自动解析可以直接访问 DLL 中的函数。 显式加载Explicit Loading 程序需要显式地通过代码来加载 DLL 并获取其函数地址。使用 LoadLibrary 函数加载 DLL并返回一个句柄表示已加载的 DLL。使用 GetProcAddress 函数根据函数名获取 DLL 中的函数地址。加载后的 DLL 需要手动卸载使用 FreeLibrary 函数释放 DLL 句柄。函数调用时需要通过函数指针来调用 DLL 中的函数。 显式加载和隐式加载主要的区别在于加载时机和加载方式。隐式加载在程序运行时自动加载 DLL并且可以直接调用 DLL 中的函数。而显式加载需要手动加载 DLL并使用函数指针来调用 DLL 中的函数。显式加载提供了更大的灵活性和控制权适用于需要在运行时动态加载和卸载 DLL 的情况而隐式加载则更加简单和方便。 六、动态链接库的静态加载 静态调用步骤 新建应用工程。通过编译器供给应用程序关于DLL的名称以及DLL函数的链接参考.h文件。这种方式不需要在程序中用代码将DLL加载到内存。将DLL和LIB文件拷贝到工程目录下将lib文件添加到工程 方式一项目属性链接依赖项lib名称方式二拖入到项目添加头文件直接调用头文件中的函数即可。   新建一个控制台项目目录结构如下 Add.h #pragma once #ifdef __cplusplus extern C { #endif // cplusplusdeclspec(dllimport) int Add(int n1, int n2);__declspec(dllimport) extern int g_nVal; #ifdef __cplusplus } #endif // __cplusplus Sub.h #pragma once #ifdef __cplusplus extern C { #endif // cplusplusdeclspec(dllimport) int Sub(int n1, int n2); #ifdef __cplusplus } #endif // __cplusplusCTest.h  #pragma once class declspec(dllimport) CTest { public:void Show(); }; .cpp #include iostream #include CTest.h #include Add.h #include Sub.h #pragma comment(lib,dll.lib)int main() {std::cout Add(1, 2) std::endl;std::cout Sub(3, 4) std::endl;std::cout std::hex g_nVal std::endl;CTest test;test.Show(); } 动态链接库与可执行文件放在同一目录下 lib文件放到根目录下 方式一使用 extern 声明外部函数 extern 关键字在C和C中都有着重要的作用它的具体含义取决于它所修饰的变量或函数。 在C语言中extern 关键字用于声明一个变量或函数是在别处定义的告诉编译器该变量或函数的定义在其他地方不在当前文件中。具体来说 外部变量声明在C语言中当你在一个文件中使用了一个全局变量而该变量的定义在另外一个文件中时你可以使用 extern 来声明该变量以便编译器知道该变量的定义在其他地方。 // 在一个文件中声明外部变量 extern int global_var; // 声明global_var是在其他文件中定义的全局变量外部函数声明extern 也可以用于声明外部函数在这种情况下它告诉编译器该函数的定义在其他地方不在当前文件中。 // 外部函数声明 extern void external_function(); // 声明external_function是在其他文件中定义的函数方式二declspec(dllimport) 声明外部函数 除了使用extern 关键字表明函数是外部定义的之外还可以使用标识符__declspec(dllimport) 来表明函数是从动态链接库中引入的。 declspec(dllimport) 与使用extern 关键字这种方式相比再使用declspec(dllimport) 标识符声明外部函数时它将告诉编译器该函数是从动态链接库中引入的编译器可以生成运行效率更高的代码。所以调用的函数来自于动态链接库则应该使用这种方式来声明外部函数。 标准来说无论是全局变量还是函数都是需要使用关键字dllimport 使用宏优化导关键字dllimport 代码如下 #pragma once #ifdef DLL_EXPORT #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif 解释一下这段代码的含义 #ifdef DLL_EXPORT这个条件编译指令用于检查是否定义了DLL_EXPORT宏。如果定义了表示当前是在编译DLL库的源代码需要导出函数和数据。如果没有定义则表示当前是在使用DLL的客户端代码需要导入函数和数据。 #define DLL_API declspec(dllexport)如果DLL_EXPORT被定义了那么将DLL_API宏定义为declspec(dllexport)。__declspec(dllexport)是在Windows平台上用于标记要导出的函数和数据的修饰符。 #else如果DLL_EXPORT未被定义执行下面的代码块。 #define DLL_API declspec(dllimport)将DLL_API宏定义为declspec(dllimport)。declspec(dllimport)是在Windows平台上用于标记要导入的函数和数据的修饰符。
    通过这种方式可以在编写DLL库时使用DLL_API宏来修饰要导出的函数和数据而在使用DLL库的客户端代码中使用DLL_API宏来修饰要导入的函数和数据。这样可以保证在编译时正确地处理导出和导入函数的修饰符。 动态链接库创建优化 预处理器包含宏DLL_EXPORT DLL_API 替换 
    declspec(dllexport)并包含 common.h 头文件 加载动态链接库优化 不需要包含这个宏即可 .h 文件 包含 common.h 文件 替换宏即可 读取全局变量来说最好直接无脑加 extern 关键字 补充在实现动态链接库时可以不导出整个类而只导出该类中的某些函数在导出类的成员函数的时候需要注意该函数必须具有public类型的访问权限。 兼容 C 如果使用C语言编写了一个DLL,那么使用C语言编写的客户端程序访问DLL中的函数就会出现问题因为后者将使用函数原始名称来调用DLL中的函数而C编译器已经对该名称进行了改编所以C语言编写的客户端程序就找不到所需的DLL导出函数。 #pragma once #ifdef DLL_EXPORT #define DLL_API extern C __declspec(dllexport) #else #define DLL_API extern C __declspec(dllimport) #endif 利用限定符 extern “C” 可以解决C和C语言之间的相互调用是函数命名问题。但是这种方法有一个缺陷就是不能用于导出一个类的成员函数和全局变量只能用于导出全局函数这种情况。 如果导出函数的调用约定发生了变化那么即使使用了限定符 extern “C” 该函数的名字仍然会发生改编。 在这种情况下可以通过一个称为模块定义文件DEF 的方式来解决名字改编问题。