VS 多工程之间管理与调用(超详细)

13 篇文章 1 订阅
				版权声明:本文为博主原创文章,未经博主允许不得转载。					https://blog.csdn.net/qq_34719188/article/details/80956749				</div>
							            <div id="content_views" class="markdown_views prism-tomorrow-night-eighties">
						<!-- flowchart 箭头图标 勿删 -->
						<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
						<p></p><div class="toc"><h3><a name="t0"></a>文章目录</h3><ul><ul><li><a href="#_1" rel="nofollow" target="_self">说明</a></li><li><a href="#_22" rel="nofollow" target="_self">配置过程描述</a></li><li><a href="#_47" rel="nofollow" target="_self">详细步骤</a></li><ul><li><a href="#1_VS_51" rel="nofollow" target="_self">1、打开 VS</a></li><li><a href="#2_55" rel="nofollow" target="_self">2、新建一个空的解决方案</a></li><li><a href="#3_4__59" rel="nofollow" target="_self">3、新建 4 个文件夹</a></li><li><a href="#4_65" rel="nofollow" target="_self">4、分别建立各自文件架下的工程</a></li><li><a href="#5_69" rel="nofollow" target="_self">5、书写源代码</a></li><li><a href="#6_335" rel="nofollow" target="_self">6、更改各种文件的生成路径</a></li><li><a href="#7_464" rel="nofollow" target="_self">7、添加引用</a></li></ul><li><a href="#_474" rel="nofollow" target="_self">失败总结</a></li><li><a href="#_488" rel="nofollow" target="_self">快速复制</a></li></ul></ul></div><p></p>

说明


本文是在前任的基础上总结完善而成的,中间走了不少弯路,希望后来人能够大树乘凉~~~

特别感谢以下两篇博文:

平台:Visual Studio 2013 , Windows 10 OS

功能:本文实现了 VS 在同一解决方案下动态库,静态库,可执行文件的生成与调用

项目下载:MultiProj项目

配置过程描述


我们最终希望的多工程目录是这样的:

这里写图片描述

用思维导图表示是这样的:

链接:MultiProj 思维导图

这里写图片描述

VS工程下是这样的

这里写图片描述

这样做的好处是:

  • 工作目录结构清晰
  • 制作安装包时我们只需将 MultiProj/Bin/Release/ 目录下的所有文件打包即可
  • 发布和转移源码的时候我们可以打包除 Temp 目录以外 MultiProj 下面的所有文件和目录(如果不需要执行档,也可不包括Bin)

详细步骤


1、打开 VS

这里写图片描述

2、新建一个空的解决方案

这里写图片描述

3、新建 4 个文件夹

这样做的好处是易于管理项目~~

这里写图片描述

4、分别建立各自文件架下的工程

这里写图片描述

5、书写源代码

MathFuncsDll 工程代码

stdafx.h (下文不再写此部分)

// stdafx.h : 标准系统包含文件的包含文件,
#pragma once
#include "targetver.h"

#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>

// TODO: 在此处引用程序需要的其他头文件

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
#include "stdafx.h"
// TODO:  在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

 
 
  • 1
  • 2
  • 3
  • 4

targetver.h (下文不再写此部分)

#pragma once

// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。

// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。

#include <SDKDDKVer.h>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

dllmain.cpp (下文不再写此部分)

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

MathFuncsDll.h

// MathFuncsDll.h

#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif

namespace MathFuncs
{
// This class is exported from the MathFuncsDll.dll
class MyMathFuncs
{
public:
// Returns a + b
static MATHFUNCSDLL_API double Add(double a, double b);

	<span class="token comment">// Returns a - b</span>
	<span class="token keyword">static</span> MATHFUNCSDLL_API <span class="token keyword">double</span> <span class="token function">Subtract</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Returns a * b</span>
	<span class="token keyword">static</span> MATHFUNCSDLL_API <span class="token keyword">double</span> <span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// Returns a / b</span>
	<span class="token comment">// Throws const std::invalid_argument&amp; if b is 0</span>
	<span class="token keyword">static</span> MATHFUNCSDLL_API <span class="token keyword">double</span> <span class="token function">Divide</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

MathFuncsDll.cpp

// MathFuncsDll.cpp : Defines the exported functions for the DLL application.
//

#include “stdafx.h”
#include “MathFuncsDll.h”
#include <stdexcept>

using namespace std;

namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}

<span class="token keyword">double</span> MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Subtract</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	<span class="token keyword">return</span> a <span class="token operator">-</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">double</span> MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Multiply</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	<span class="token keyword">return</span> a <span class="token operator">*</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">double</span> MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Divide</span><span class="token punctuation">(</span><span class="token keyword">double</span> a<span class="token punctuation">,</span> <span class="token keyword">double</span> b<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>b <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
	<span class="token punctuation">{</span>
		throw <span class="token function">invalid_argument</span><span class="token punctuation">(</span><span class="token string">"b cannot be zero!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">return</span> a <span class="token operator">/</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
MathSquare 工程代码

square.cpp

#include <iostream>
using namespace std;

int main(){
cout << “Pls enter two number : \n”;
int a, b;
cin >> a >> b;
cout << a + b << endl;
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
MathAverageLib 工程代码

MathOperator.h

#pragma once
class MathOperator
{
public:
	MathOperator();
	~MathOperator();
<span class="token keyword">int</span> <span class="token function">getAverage</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span> <span class="token keyword">int</span> b<span class="token punctuation">,</span> <span class="token keyword">int</span> c<span class="token punctuation">)</span><span class="token punctuation">;</span>

};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

MathOperator.cpp

#include "stdafx.h"
#include "MathOperator.h"

MathOperator::MathOperator()
{
}

MathOperator::~MathOperator()
{
}

int MathOperator::getAverage(int a, int b, int c){
return ( a + b + c) / 3;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
Main工程代码

main.cpp

#include <iostream>
#include <windows.h>

#include “MathOperator.h”
#include “MathFuncsDll.h”

using namespace std;

int main()
{
///test dll
double a = 7.4;
int b = 99;

cout <span class="token operator">&lt;&lt;</span> <span class="token string">"a + b = "</span> <span class="token operator">&lt;&lt;</span>
	MathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span>MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Add</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>
cout <span class="token operator">&lt;&lt;</span> <span class="token string">"a - b = "</span> <span class="token operator">&lt;&lt;</span>
	MathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span>MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Subtract</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>
cout <span class="token operator">&lt;&lt;</span> <span class="token string">"a * b = "</span> <span class="token operator">&lt;&lt;</span>
	MathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span>MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Multiply</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>
cout <span class="token operator">&lt;&lt;</span> <span class="token string">"a / b = "</span> <span class="token operator">&lt;&lt;</span>
	MathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span>MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Divide</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>

try
<span class="token punctuation">{</span>
	cout <span class="token operator">&lt;&lt;</span> <span class="token string">"a / 0 = "</span> <span class="token operator">&lt;&lt;</span>
		MathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span>MyMathFuncs<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">Divide</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
catch <span class="token punctuation">(</span><span class="token keyword">const</span> invalid_argument <span class="token operator">&amp;</span>e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	cout <span class="token operator">&lt;&lt;</span> <span class="token string">"Caught exception: "</span> <span class="token operator">&lt;&lt;</span> e<span class="token punctuation">.</span><span class="token function">what</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> endl<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/// test lib </span>
MathOperator mo<span class="token punctuation">;</span>
std<span class="token punctuation">:</span><span class="token punctuation">:</span>cout <span class="token operator">&lt;&lt;</span> <span class="token string">"The average of 2, 4, 6 is: "</span> <span class="token operator">&lt;&lt;</span> mo<span class="token punctuation">.</span><span class="token function">getAverage</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&lt;&lt;</span> std<span class="token punctuation">:</span><span class="token punctuation">:</span>endl<span class="token punctuation">;</span>

<span class="token comment">///test exe</span>
<span class="token function">WinExec</span><span class="token punctuation">(</span><span class="token string">"\"MathSquare.exe\""</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">system</span><span class="token punctuation">(</span><span class="token string">"pause"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

部分代码讲解

这里写图片描述
这里写图片描述
这里写图片描述

6、更改各种文件的生成路径

首先看一下项目设置中可以使用的宏,常用的有:

宏名称含义
$(ConfigurationName)Debug或者Release
$(IntDir)编译器使用的中间目录,产出obj二进制文件
$(OutDir)链接器使用的输出目录
$(ProjectDir)项目目录
$(ProjectName)项目名字
$(SolutionDir)解决方案目录
$(TargetDir)目标输出文件所在的目录
$(TargetExt)目标输出的扩展名
$(TargetFileName)目标输出文件名,包括扩展名
$(TargetName)目标输出名,不包括扩展名
$(TargetPath)目标输出文件的全路径名

上面建立的 4 个工程要分别单独设置,每个工程又要分 Debug 和 Release 两种情况,所以要注意!!!

MathFuncsDll 属性设置

这里写图片描述

全局配置

  • 配置属性 - 常规 - 输出目录:
$(SolutionDir)\Temp\Link\$(ProjectName)\$(ConfigurationName)

 
 
  • 1
  • 配置属性 - 常规 - 中间目录:
$(SolutionDir)\Temp\Compile\$(ProjectName)\$(ConfigurationName)

 
 
  • 1

Release 模式

  • 配置属性 - 生成事件 - 后期生成事件 - 命令行:
copy $(TargetPath)    $(SolutionDir)\Bin\$(ConfigurationName)\;
copy $(TargetDir)$(TargetName).lib    $(SolutionDir)\Lib\;

 
 
  • 1
  • 2

Debug 模式

  • 配置属性 - 链接器 - 高级 - 导入库:
$(TargetDir)$(TargetName)_d.lib

 
 
  • 1
  • 配置属性 - 生成事件 - 后期生成事件 - 命令行:
copy $(TargetPath)    $(SolutionDir)\Bin\$(ConfigurationName)\;
copy $(TargetDir)$(TargetName)_d.lib    $(SolutionDir)\Lib\;

 
 
  • 1
  • 2

看不清楚的话看这里:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

MathSquare 属性设置

这里写图片描述

全局配置

  • 配置属性 - 常规 - 输出目录(同上)
  • 配置属性 - 常规 - 中间目录(同上)
  • 配置属性 - 生成事件 - 后期生成事件 - 命令行:
copy  $(TargetDir)$(TargetName).exe    $(SolutionDir)\Bin\$(ConfigurationName);

 
 
  • 1
MathAverageLib 属性设置

这里写图片描述

全局配置

  • 配置属性 - 常规 - 输出目录(同上)
  • 配置属性 - 常规 - 中间目录(同上)
  • 配置属性 - 生成事件 - 后期生成事件 - 命令行:
copy $(TargetDir)$(TargetName).lib $(SolutionDir)\Lib\;

 
 
  • 1
Main 属性设置

全局配置

  • 配置属性 - 常规 - 输出目录(同上)
  • 配置属性 - 常规 - 中间目录(同上)
  • 配置属性 - 生成事件 - 后期生成事件 - 命令行:
copy $(TargetPath)    $(SolutionDir)\Bin\$(ConfigurationName);

 
 
  • 1

7、添加引用

这里写图片描述

大功告成!!! Ctrl + F5 运行即可~~

失败总结


  • 是否正确建立工程
  • 时否正确配置相关属性
  • 是否模糊了 release 和 debug 下的配置
  • 是否写正确后处理事件
  • 源代码是都书写正确

快速复制

// 输出目录
$(SolutionDir)\Temp\Link\$(ProjectName)\$(ConfigurationName)
// 中间目录
$(SolutionDir)\Temp\Compile\$(ProjectName)\$(ConfigurationName)

// DLL Release 命令
copy $(TargetPath) $(SolutionDir)\Bin$(ConfigurationName)<span class=“token punctuation”>;
copy &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ( &lt; / s p a n &gt; T a r g e t D i r &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ) &lt; / s p a n &gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TargetDir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; <spanclass="tokenpunctuation">(</span>TargetDir<spanclass="tokenpunctuation">)</span>(TargetName).lib $(SolutionDir)\Lib<span class=“token punctuation”>;

// DLL Debug 命令
copy $(TargetPath) $(SolutionDir)\Bin$(ConfigurationName)<span class=“token punctuation”>;
copy &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ( &lt; / s p a n &gt; T a r g e t D i r &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ) &lt; / s p a n &gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TargetDir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; <spanclass="tokenpunctuation">(</span>TargetDir<spanclass="tokenpunctuation">)</span>(TargetName)_d.lib $(SolutionDir)\Lib<span class=“token punctuation”>;

&lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ( &lt; / s p a n &gt; T a r g e t D i r &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ) &lt; / s p a n &gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TargetDir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; <spanclass="tokenpunctuation">(</span>TargetDir<spanclass="tokenpunctuation">)</span>(TargetName)_d.lib

// EXE 命令
copy &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ( &lt; / s p a n &gt; T a r g e t D i r &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ) &lt; / s p a n &gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TargetDir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; <spanclass="tokenpunctuation">(</span>TargetDir<spanclass="tokenpunctuation">)</span>(TargetName).exe $(SolutionDir)\Bin$(ConfigurationName);

// LIB 命令
copy &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ( &lt; / s p a n &gt; T a r g e t D i r &lt; s p a n c l a s s = &quot; t o k e n p u n c t u a t i o n &quot; &gt; ) &lt; / s p a n &gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TargetDir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; <spanclass="tokenpunctuation">(</span>TargetDir<spanclass="tokenpunctuation">)</span>(TargetName).lib $(SolutionDir)\Lib<span class=“token punctuation”>;

// MAIN 命令
copy $(TargetPath) $(SolutionDir)\Bin$(ConfigurationName);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
        </div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7b4cdcb592.css" rel="stylesheet">
            </div>
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值