很好的c++和Python混合编程文章

38 篇文章 2 订阅

很好的c++和Python混合编程文章

jackyhwei 发布于 2010-06-03 21:05 点击:7385次 
来自:cppblog.com
本人是用vc2003+python2.5学习的,其它的也应该差不了多少 0. 坏境设置 把python的include/libs目录分别加到vc的include/lib directories中去。
TAG:  boost   Python   混编   Python入门  

c++中嵌入python入门1

本人是用vc2003+python2.5学习的,其它的也应该差不了多少

0. 环境设置
把python的include/libs目录分别加到vc的include/lib directories中去。另外,由于python没有提供debug lib,体地说,就是没有提供python25_d.lib了。你可以自己编译python的源代码来得到python25_d.lib的,偶还没试过,呵呵。而且网上找了一下也没下载到。所以,如果你想要在debug下运行程序的话,你要把pyconfig.h(在python25/include/目录下)的大概是在283行,把pragma comment(lib,"python25_d.lib")改成pragma comment(lib,"python25.lib"),让python都使用非debug lib.

1. 开始编程了
#include <python.h>
第一步就是包含python的头文件

2. 看一个很简单的例子
1)python文件test.py,很简单的定义了一个函数

      
      
  1. #Filename test.py 
  2. def Hello(): 
  3.     print "Hello, world!" 

这个应该能看懂的吧?否则的话,回去再练练python吧,呵呵。《简明Python教程》Swaroop, C. H. 著。沈洁元  译。

2)cpp文件

      
      
  1. #include <python.h> //包含头文件,在c++中嵌入python,这是必须的 
  2. int main() 
  3.  Py_Initialize(); 
  4.  
  5.  PyObject * pModule = NULL; 
  6.  PyObject * pFunc   = NULL; 
  7.  
  8.  pModule = PyImport_ImportModule("test"); 
  9.  pFunc   = PyObject_GetAttrString(pModule, "Hello"); 
  10.  PyEval_CallObject(pFunc, NULL); 
  11.  
  12.  Py_Finalize(); 
  13.  
  14.  return 0; 

第一步还是包含头文件

第二步,使用python之前,要调用Py_Initialize();这个函数进行初始化。
帮助文档中如是说:
The basic initialization function is Py_Initialize(). This initializes the table of loaded modules, and creates the fundamental modules __builtin__, __main__, sys, and exceptions. It also initializes the module search path (sys.path).

反正,一开始你一定要调用。

第三步,声明一些Python的变量,PyObject类型的。其实声明也可放在前面,这个倒是无所谓的。

第四步,import module,也就是你的脚本名字,不需要加后缀名,否则会出错的。

第五步,从你import进来的module中得到你要的函数
 pFunc   = PyObject_GetAttrString(pModule, "Hello");
上面的例子已经够清楚的了,最后一个是你要得到的函数的名字

第六步,调用PyEval_CallObject来执行你的函数,第二个参数为我们要调用的函数的函数,本例子不含参数,所以设置为NULL。

第七步,调用Py_Finalize,这个根Py_Initialize相对应的。一个在最前面,一个在最后面。

第一次写教程。这个例子非常简单,本人也还在学习当中阿,只能保证大家能够把这个例子运行起来。建议大家去看python的documentaion,里面有讲怎么embedding python的。先写到这里,其实目前也只学到这么多,呵呵。下次学了更多以后再写。Over。恩。 (jacky2019)


很好的c++和Python混合编程文章(2)

jackyhwei 发布于 2010-06-03 21:05 点击:7386次 
来自:cppblog.com
c++中嵌入python入门2 1. 一个有一个参数的例子 python文件 #Filenametest2.py def Hello(s): print Hello,world! print s cpp文件 #includepython.h int main() { Py_Initialize(); PyObject*pModule=NULL; PyObje
TAG:  boost   Python   混编   Python入门  

c++中嵌入python入门2

1. 一个有一个参数的例子

python文件

             
             
  1. #Filename test2.py 
  2.  
  3. def Hello(s): 
  4.     print "Hello, world!" 
  5.     print s 

cpp文件

             
             
  1. #include <python.h> 
  2. int main() 
  3.  Py_Initialize(); 
  4.  
  5.  PyObject * pModule = NULL; 
  6.  PyObject * pFunc   = NULL; 
  7.  PyObject * pArg    = NULL; 
  8.  
  9.  pModule = PyImport_ImportModule("test2"); 
  10.  pFunc   = PyObject_GetAttrString(pModule, "Hello"); 
  11.  pArg    = Py_BuildValue("(s)""function with argument"); 
  12.  
  13.  PyEval_CallObject(pFunc, pArg); 
  14.  
  15.  Py_Finalize(); 
  16.  
  17.  return 0; 

注意,参数要以tuple元组形式传入。因为这个函数只要一个参数,所以我们直接使用(s)构造一个元组了。

2. 一个有两个参数的例子

python文件中加入以下代码,一个加函数

             
             
  1. def Add(a, b): 
  2.     print "a+b=", a+b 

cpp文件,只改了两行,有注释的那两行

             
             
  1. #include <python.h> 
  2. int main() 
  3.  Py_Initialize(); 
  4.  
  5.  PyObject * pModule = NULL; 
  6.  PyObject * pFunc   = NULL; 
  7.  PyObject * pArg    = NULL; 
  8.  
  9.  pModule = PyImport_ImportModule("test2"); 
  10.  pFunc   = PyObject_GetAttrString(pModule, "Add");//终于告别hello world了,开始使用新的函数 
  11.  pArg    = Py_BuildValue("(i,i)", 10, 15);//构造一个元组 
  12.  
  13.  PyEval_CallObject(pFunc, pArg); 
  14.  
  15.  Py_Finalize(); 
  16.  
  17.  return 0; 
  18. }

其它的就类似了。。。基本上,我们知道了怎么在c++中使用python中的函数。接下来学习一下如何使用python中的class。

附:Py_BuildValue的使用例子,来自python documentation:

    Py_BuildValue("")                        None
    Py_BuildValue("i", 123)                  123
    Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
    Py_BuildValue("s", "hello")              'hello'
    Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
    Py_BuildValue("s#", "hello", 4)          'hell'
    Py_BuildValue("()")                      ()
    Py_BuildValue("(i)", 123)                (123,)
    Py_BuildValue("(ii)", 123, 456)          (123, 456)
    Py_BuildValue("(i,i)", 123, 456)         (123, 456)
    Py_BuildValue("[i,i]", 123, 456)         [123, 456]
    Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
    Py_BuildValue("((ii)(ii)) (ii)",1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))

(jacky2019)

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自: 罗索实验室 [ http://www.rosoo.net/a/201006/9574.html]

很好的c++和Python混合编程文章(3)

jackyhwei 发布于 2010-06-03 21:05 点击:7387次 
来自:cppblog.com
c++中嵌入python入门3 这次主要讲讲怎么把python中的class嵌入到c++中去。顺便讲讲元组的操作和怎么编译python源代码。 1. 首先讲讲元组的操作 由于参数是通过元组传进去的,所以我们不能老是通过Py_BuildValue这个
TAG:  boost   Python   混编   Python入门  

c++中嵌入python入门3

这次主要讲讲怎么把python中的class嵌入到c++中去。顺便讲讲元组的操作和怎么编译python源代码。

1. 首先讲讲元组的操作
由于参数是通过元组传进去的,所以我们不能老是通过Py_BuildValue这个函数来操作元组,那样太不方便了。
Python提供了元组相关的操作,下面这个例子演示了如何操作。主要是下面几个函数:

            
            
  1. //new一个元组,传入size 
  2. pArgs = PyTuple_New(argc - 3);  
  3. //set元组的直,第一个为元组,第二个为index(从0开始),第三个为value 
  4. PyTuple_SetItem(pArgs,0,Py_BuildValue("i",2000) ); 
  5. PyTuple_SetItem(pArgs,1,Py_BuildValue("i",8) ); 

来自python doc的一个例子

            
            
  1. #include <Python.h> 
  2. int main(int argc, char *argv[]) 
  3.     PyObject *pName, *pModule, *pDict, *pFunc; 
  4.     PyObject *pArgs, *pValue; 
  5.     int i; 
  6.  
  7.     if (argc < 3) { 
  8.         fprintf(stderr,"Usage: call pythonfile funcname [args]\n"); 
  9.         return 1; 
  10.     } 
  11.  
  12.     Py_Initialize(); 
  13.     pName = PyString_FromString(argv[1]); 
  14.     /* Error checking of pName left out */ 
  15.  
  16.     pModule = PyImport_Import(pName); 
  17.     Py_DECREF(pName); 
  18.  
  19.     if (pModule != NULL) { 
  20.         pFunc = PyObject_GetAttrString(pModule, argv[2]); 
  21.         /* pFunc is a new reference */ 
  22.  
  23.         if (pFunc && PyCallable_Check(pFunc)) { 
  24.             pArgs = PyTuple_New(argc - 3); 
  25.             for (i = 0; i < argc - 3; ++i) { 
  26.                 pValue = PyInt_FromLong(atoi(argv[i + 3])); 
  27.                 if (!pValue) { 
  28.                     Py_DECREF(pArgs); 
  29.                     Py_DECREF(pModule); 
  30.                     fprintf(stderr, "Cannot convert argument\n"); 
  31.                     return 1; 
  32.                 } 
  33.                 /* pValue reference stolen here: */ 
  34.                 PyTuple_SetItem(pArgs, i, pValue); 
  35.             } 
  36.             pValue = PyObject_CallObject(pFunc, pArgs); 
  37.             Py_DECREF(pArgs); 
  38.             if (pValue != NULL) { 
  39.                 printf("Result of call: %ld\n", PyInt_AsLong(pValue)); 
  40.                 Py_DECREF(pValue); 
  41.             } 
  42.             else { 
  43.                 Py_DECREF(pFunc); 
  44.                 Py_DECREF(pModule); 
  45.                 PyErr_Print(); 
  46.                 fprintf(stderr,"Call failed\n"); 
  47.                 return 1; 
  48.             } 
  49.         } 
  50.         else { 
  51.             if (PyErr_Occurred()) 
  52.                 PyErr_Print(); 
  53.             fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); 
  54.         } 
  55.         Py_XDECREF(pFunc); 
  56.         Py_DECREF(pModule); 
  57.     } 
  58.     else { 
  59.         PyErr_Print(); 
  60.         fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); 
  61.         return 1; 
  62.     } 
  63.     Py_Finalize(); 
  64.     return 0; 

2. class操作
把下面加入到test2.py中去。定义了一个很简单的类,有一个name成员变量,一个printName成员函数

            
            
  1. class TestClass: 
  2.     def __init__(self,name): 
  3.         self.name = name 
  4.  
  5.     def printName(self): 
  6.         print self.name 

cpp文件

            
            
  1. #include <python.h> 
  2. int main() 
  3.  Py_Initialize(); 
  4.  
  5.  PyObject * pModule = NULL; 
  6.  PyObject * pFunc   = NULL; 
  7.  PyObject * pArg    = NULL; 
  8.  PyObject * pClass  = NULL; 
  9.  PyObject * pObject = NULL; 
  10.  
  11.  pModule = PyImport_ImportModule("test2"); 
  12.  pClass  = PyObject_GetAttrString(pModule, "TestClass");//得到那个类 
  13.  pArg = PyTuple_New(1); 
  14.  PyTuple_SetItem(pArg, 0, Py_BuildValue("s""Jacky")); 
  15.  pObject = PyEval_CallObject(pClass, pArg);//生成一个对象,或者叫作实例 
  16.  
  17.  pFunc = PyObject_GetAttrString(pObject, "printName");//得到该实例的成员函数 
  18.  PyEval_CallObject(pFunc, NULL);//执行该实例的成员函数 
  19.  
  20.  Py_Finalize(); 
  21.  
  22.  return 0; 

没有什么资料,就先写到这里了。下面介绍一下怎么build python25的源代码

3. 编译python源代码
为什么要编译呢?因为没有python25_d.lib!呵呵。顺便可以了解一下代码结构。
解压缩后,有好多目录,其中pcbuild和pcbuild8是我们要的。pcbuild对应着vc7.1的,pcbuild8对应着vc8.0的
因为在用vc7.1,也就是2003了。所以我就说说怎么用2003来编译吧。事实上是从一位牛人那里学来的

http://blog.donews.com/lemur/archive/2005/12/17/660973.aspx,那位大哥大概一年半前就在解剖python了,厉害阿。看来我只能后来居上了,娃哈哈。我按照他说的试了一下,编译成功!

不过遇到一点小问题,用vc2003打开那个solution的时候,发现作者没有把source code control去掉,郁闷!害的我

们打开的时候一堆messagebox。不过不用管它就好了,一直确定。最后试了一下那个python25_d.lib,没问题。不过记

得把python25_d.dll copy到一个能被找到的目录,比如说c:\windows\system32\下面。python25.dll也在这个目录下

面。over。恩。 (jacky2019)

很好的c++和Python混合编程文章(4)

jackyhwei 发布于 2010-06-03 21:05 点击:7388次 
来自:cppblog.com
c++中嵌入python入门4 之 Boost.Python 坏境python25 + vs2005 (2005真耗资源阿。。。) 有一段时间没写blog了。这几天都在研究怎么封装c++,让python可以用c++的库。在网上发现了boost.python这个好咚咚。不 过在使
TAG:  boost   Python   混编   Python入门  

c++中嵌入python入门4 之 Boost.Python

坏境python25 + vs2005 (2005真耗资源阿。。。)

有一段时间没写blog了。这几天都在研究怎么封装c++,让python可以用c++的库。在网上发现了boost.python这个好咚咚。不

过在使用过程中碰到一点问题。本文教大家如何把

             
             
  1. char const* greet() 
  2.    return "hello, world"

封装成python。实际上这是python教程里面的咚咚。

首先下载Boost,www.boost.org。boost.python在boost里面了。在visual studio 2005 command prompt中navigation到boost\boost_1_34_0\下。记得一定要用visual studio 2005 command prompt这个vs2005带的tools,不要用cmd.exe,否则会碰到很多错误的。然后就是把bjam.exe拷贝到一个能被找到的目录下,或者直接也拷贝到boost\boost_1_34_0\下即可。然后,设置python的根目录和python的版本,也可直接把它们加到坏境目录中,那样就不用每次都设置一下。
set PYTHON_ROOT=c:/python25
set PYTHON_VERSION=2.5

接着就可以直接运行了,bjam -sTOOLS=vc-8_0
整个编译过程要很长时间。。。

成功之后,就会有好多个boost_python-vc80-****.dll,.lib的,把他们都拷贝到一个能被系统找到的目录,不妨直接把他们都扔到c:\windows\system32下。

接着,我们开始编译hello。navigation到boost\boost_1_34_0\libs\python\example\tutorial下,bjam -sTOOLS=vc-8_0运行,在bin的目录下即会生成hello.pyd。这下就基本成功了,如果没成功的话,check一下上面boost_python的那些dll能否被系统找到。另外,这里有python25的一个bug。。。我花了很长时间才在python的mail lists中找到了。寒。。。

错误如下所示:
D:\Learn\Python\boost\boost_1_34_0\libs\python\example\tutorial>bjam
Jamroot:17: in modules.load
rule python-extension unknown in module Jamfile</D:/Learn/Python/boost/boost_1_3
4_0/libs/python/example/tutorial>.
D:/Learn/Python/boost/boost_1_34_0/tools/build/v2/build\project.jam:312: in load
-jamfile
D:/Learn/Python/boost/boost_1_34_0/tools/build/v2/build\project.jam:68: in load
D:/Learn/Python/boost/boost_1_34_0/tools/build/v2/build\project.jam:170: in proj
ect.find
D:/Learn/Python/boost/boost_1_34_0/tools/build/v2\build-system.jam:237: in load
D:\Learn\Python\boost\boost_1_34_0\libs\python\example\..\..\..\tools\build\v2/k
ernel\modules.jam:261: in import
D:\Learn\Python\boost\boost_1_34_0\libs\python\example\..\..\..\tools\build\v2/k
ernel/bootstrap.jam:132: in boost-build
D:\Learn\Python\boost\boost_1_34_0\libs\python\example\boost-build.jam:7: in mod
ule scope

解决办法如下:
在boost\boost_1_34_0\tools\build\v2\目录下找到user-config.jam文件,打开在import toolset : using ;
下面加一行代码:
using python ;
再重新编译一下boost,然后就没问题了。tutorial里面的hello能顺利编译通过。ps.这个问题困扰了我好长时间。。sigh。。。

编译成功后会产生一个hello.pyd,在bin的目录下面。

有好多办法测试此hello.pyd是否可以用。
方法一,把它拷贝到python25\dlls下,打开IDLE,
>>> import hello
>>> hello.greet()
'hello, world'
>>> 
方法二,直接在当前目录下写一个python文件,然后直接调用hello.pyd即可。总之,hello.pyd就是一个python文件了。。嗯。操作hello.pyd根其他python文件是一样的。
这样就成功了。

如果碰到如下错误,是因为系统找不到boost_python的dll。强烈建议把他们都扔到system32下!。

>>> import hello

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import hello
ImportError: DLL load failed: 找不到指定的模块。
>>>

说明,hello.cpp在boost\boost_1_34_0\libs\python\example\tutorial目录下。里面的内容是:

             
             
  1. //  Copyright Joel de Guzman 2002-2004. Distributed under the Boost 
  2. //  Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt 
  3. //  or copy at http://www.boost.org/LICENSE_1_0.txt) 
  4. //  Hello World Example from the tutorial 
  5. //  [Joel de Guzman 10/9/2002] 
  6.  
  7. char const* greet() 
  8.    return "hello, world"
  9.  
  10. #include <boost/python/module.hpp> 
  11. #include <boost/python/def.hpp> 
  12. using namespace boost::python; 
  13.  
  14. BOOST_PYTHON_MODULE(hello) 
  15.     def("greet", greet); 

其中

             
             
  1. BOOST_PYTHON_MODULE(hello) 
  2.     def("greet", greet); 

是对greet从c++向python的一个封装声明吧,装换就交给boost了。

先写到这里了。下次再写。。嗯 (jacky2019)

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人
python与c++交互学习入门之5 这次讲讲,如何扩展c++库。通过boost.python把c++库编译成python能够调用的dll。 通过上一次的教程后,大家都应该会使用boost.python了。把c++程序编译成pyd文件。由于c++有很多特性,
TAG:  boost   Python   混编   Python入门  

python与c++交互学习入门之5

这次讲讲,如何扩展c++库。通过boost.python把c++库编译成python能够调用的dll。


通过上一次的教程后,大家都应该会使用boost.python了。把c++程序编译成pyd文件。由于c++有很多特性,所以,如果你的程

序用了很多的c++特性的话,那么你必须做很多工作了。像虚拟函数,函数重载,继承,默认值等等。具体如何转化,请参

boost.python的文档了。


这几天尝试着把c++程序库编译成python可调用的dll,不知道为什么一直不可用。。很是郁闷。老是显示如下的错误:

            
            
  1. Traceback (most recent call last): 
  2.   File "<pyshell#3>", line 1in <module> 
  3.     import pydll 
  4. ImportError: No module named pydll 

意思是说找不到dll。我把dll都copy到python/dlls下了还是不行,而且我确定python的sys.path包含了python/dlls目录了。

很是不解。网上也很难找到资料,google了很长时间找不到有用的资料,好像中文方面的资料很少的。今天尝试了一下google

英文资料,终于有了新的发现:
http://mail.python.org/pipermail/c++-sig/2007-February/011971.html
You are using Python2.5. In this version of Python you have to have file extension to be "pyd" - sge.pyd

-- 
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/

有人碰到的问题跟我的是一样的。后面那个Roman回答了一下,是文件扩展名的问题!!!为什么不支持dll呢?不解。回去试

了一下把后缀名改了就成功了。。。why???


下面来看一下我的那个简单的例子:
这个例子来自于网上,
http://www.vckbase.com/document/viewdoc/?id=1540
C++ 扩展和嵌入 Python
作者:胡金山
源码下载地址:http://www.vckbase.com/code/downcode.asp?id=2777

这是一个非常简单的dll工程。给python提供了一个函数static PyObject* Recognise(PyObject *self, PyObject *args)。

1、不使用boost.python库来直接构建dll
接下来,我们来用C++为Python编写扩展模块(动态链接库),并在Python程序中调用C++开发的扩展功能函数。生成一个取名为

pyUtil的Win32 DLL工程,除了pyUtil.cpp文件以外,从工程中移除所有其它文件,并填入如下的代码:

            
            
  1. // pyUtil.cpp 
  2. #ifdef PYUTIL_EXPORTS 
  3. #define PYUTIL_API __declspec(dllexport) 
  4. #else 
  5. #define PYUTIL_API __declspec(dllimport) 
  6. #endif 
  7.  
  8. #include<windows.h> 
  9. #include<string> 
  10. #include<Python.h> 
  11. BOOL APIENTRY DllMain( HANDLE hModule, 
  12.                        DWORD  ul_reason_for_call, 
  13.                        LPVOID lpReserved 
  14.         ) 
  15.     switch (ul_reason_for_call) 
  16.     { 
  17.     case DLL_PROCESS_ATTACH: 
  18.     case DLL_THREAD_ATTACH: 
  19.     case DLL_THREAD_DETACH: 
  20.     case DLL_PROCESS_DETACH: 
  21.         break
  22.     } 
  23.     return TRUE; 
  24. std::string Recognise_Img(const std::string url) 
  25.     //返回结果 
  26.     return "从dll中返回的数据... : " +url; 
  27. static PyObject* Recognise(PyObject *self, PyObject *args) 
  28.     const char *url; 
  29.     std::string sts; 
  30.     if (!PyArg_ParseTuple(args, "s", &url)) 
  31.         return NULL; 
  32.     sts = Recognise_Img(url); 
  33.     return Py_BuildValue("s", sts.c_str() ); 
  34. static PyMethodDef AllMyMethods[] = { 
  35.     {"Recognise",  Recognise, METH_VARARGS},//暴露给Python的函数 
  36.     {NULL,      NULL}        /* Sentinel */ 
  37. }; 
  38. extern "C" PYUTIL_API void initpyUtil() 
  39.     PyObject *m, *d; 
  40.     m = Py_InitModule("pyUtil", AllMyMethods); //初始化本模块,并暴露函数 
  41.     d = PyModule_GetDict(m); 

Python代码中调用这个动态链接库: (记得把dll的扩展名改为.pyd,另外dll的路径要能够被检索到)

            
            
  1. import pyUtil 
  2. result = pyUtil.Recognise("input url of specific data"
  3. print "the result is: "+ result 

2、使用boost.python库来构建dll
用C++为Python写扩展时,如果您愿意使用Boost.Python库的话,开发过程会变得更开心J,要编写一个与上述pyUtil同样功能的动态链接库,只需把文件内容替换为下面的代码。当然,编译需要boost_python.lib支持,运行需要boost_python.dll支持。

            
            
  1. #include<string> 
  2. #include <boost/python.hpp> 
  3. using namespace boost::python; 
  4. #pragma comment(lib, "boost_python.lib") 
  5. std::string strtmp; 
  6. char const* Recognise(const char* url) 
  7.     strtmp ="从dll中返回的数据... : "
  8.     strtmp+=url; 
  9.     return strtmp.c_str(); 
  10. BOOST_PYTHON_MODULE(pyUtil) 
  11.     def("Recognise", Recognise); 

可以非常明显地看到,用了boost.python库之后,简单了很多。因为boost.python为你做了很多的事情。。恩。好像没有讲很多有用的东西,光顾着讲了,呵呵。。。我也还在继续学习之中。下次写点什么呢?继续学习了哦

原文:http://www.cppblog.com/jacky2019/archive/2007/05/17/24269.html

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值