matlab的combuilder系列-matlab下做com组件

发信人: xxhn (小湖南), 信区: MathTools       
  : matlabcombuilder系列-matlab下做com组件

发信站: BBS 水木清华站 (Wed May 21 10:24:09 2003)

com builder
matlab6.5才有的,也是mathworks公司推荐使用于混合编程的,这些日子我

对他进行了全方位的摸索,感觉是爽呆了,下面我们一起来揭开它的神秘面纱,^_^
     
此系列分为以下几块:
     1.matlab
下做com组件
     2.vb,c#.net
实现调用
     3.vc
实现调用
     4.
打包
     5.
优缺点评注
其中2,3部分可以选择一个看

matlab下做com组件
     com
component object module的简称,它是一种通用的对象接口,任何语言只要按照
这种接口标准,就可以实现调用它。matlab6.5新推出来的combuilder就是把matlab下的程
序做成com组件,供其他语言调用。
     
我们先准备两个测试文件,并copy一个图片到c盘下,起名叫1.jpg(这些你都可以改
的,我这儿是为了程序方便)
     
第一个叫im_test.m如下:
     function im_test              %
这个文件不带输入与输出

     I=imread('c:/1.jpg');         %
因为以前带有imshow的程序用mcc编成dll后用不
                                   %
了,所以想试combuilder是否
     imshow(I);                    %
能支持这些函数
     
第二个叫split2rgb.m,就是前些日子Zosco发给我的那个程序,因为它用mcc编成dl
l
后有问题,所以我在这儿继续将它进行测试,而且它也带有多个输入及输出参数,所以也

正好拿来测试
     
matlabworkspace下打comtool,就打开了matlab com builder,点击file-new 
project
,新建一个工程,在component name里填上comtestClass name里填上一个
sglt
est(
并将自动生成classes里的comtest remove
),complie 
code in
cc++都无所谓,将Complier options里的Use Handle Graphics library的复

选框画上,点击ok就行了。然后点击project--Add files,im_test.msplit2rgb.m添加
入工程,然后点Build-Com Object,就会在comtest/distrib/文件夹下生成一个comtest_
1_0.dll(
它就是做好的com组件)Buildmatlab已经自动将此dll在注册表中注册,为了下

面能用其他编译器调用,我们还需做一个准备工作,开一个dos窗口,进入<matlabroot>/
bin/win32
目录下(matlabroot为你机器上matlab安装的路径),
regsvr32 mwcomutil.dll
,即对mwcomutil.dll进行注册(这个dllmatlab下作的任何com组件都要用到的dll),下面

我们在其他编译器下调用时就可以用了。
     ^_^
,是不是觉得做起com组件来很简单呢,matlab下可以给com组件中的类添加成员
、事件、方法等,我这儿其实是给类sgltest添加了两个方法,怎么添加成员和方法可以参
matlabcom builder的帮助。

附录:split2rgb.m的源代码
 %%//   
测试文件
function [m_nHeight,m_nWidth,mOrigR,mOrigG,mOrigB]=Split2RGB(FileName)

%%//  
读入一个Jpg文件,
mOrigData=imread(FileName);
%mDestData=imresize(mOrigData,0.5);
imwrite(mOrigData,'c:/2.jpg');

%%//  
用三个变量保存其R,G,B分量
mOrigR=mOrigData(:,:,1);
mOrigG=mOrigData(:,:,2);
mOrigB=mOrigData(:,:,3);


%%//  
获得图象的高度,宽度
[m_nHeight,m_nWidth]=size(mOrigR);

figure(1);
set(gcf,'MenuBar','none')
imshow(mOrigData);
title(['Orginal Image:',FileName],'Color','b','FontSize',14);
xlabel(['Height: ',num2str(m_nHeight),'    Width :',num2str(m_nWidth)],'Color'
,'b','FontSize',12);


%%//  
param文件
paraFName=[FileName(1:length(FileName)-4),'.param'];
fid=fopen(paraFName,'w');
fwrite(fid,m_nHeight,'uint32');
fwrite(fid,m_nWidth,'uint32');
fclose(fid);

%%//   
 R 分量文件
RFName=[FileName(1:length(FileName)-4),'_R.rot'];
fid=fopen(RFName,'w');
fwrite(fid,mOrigR,'uint8');
fclose(fid);

%%//   
 G 分量文件
GFName=[FileName(1:length(FileName)-4),'_G.rot'];
fid=fopen(GFName,'w');
fwrite(fid,mOrigG,'uint8');
fclose(fid);

%%//   
 B 分量文件
BFName=[FileName(1:length(FileName)-4),'_B.rot'];
fid=fopen(BFName,'w');
fwrite(fid,mOrigB,'uint8');
fclose(fid);

--
 come on,baby!


※ 
来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools       
  : matlabcombuilder系列-vb,c#.net调用

发信站: BBS 水木清华站 (Wed May 21 10:24:38 2003)

这一部分讲vb,c#.net下怎么实现调用上一部分我们生成的comtest_1_0.dll(matlab下做的

com
组件),记得一定先要对mwcomutil.dll进行注册(怎么注册参看上一部分)
1.vb
下实现调用

    
打开或新建一个vb工程,点project-Reference,在弹出来的窗口中找到comtest 1.0 
Type Library,
将前面的复选框选上,点击ok,此时便将此com组件添加到工程里面去了,

此时你可以用对象浏览器看到comtest下有个sgltest类,这个类里面有两个方法im_test,
split2rgb,
还有个MWFlags成员(这个成员是自动生成的),vb下测试代码如下
:
    
测试im_test方法的代码
:
    Dim st As sgltest
    Set st = New sgltest
    Call st.im_test
    
测试split2rgb方法的代码
:
    Dim st As sgltest
    Set st = New sgltest
    Dim h As Variant, w As Variant, r As Variant, g As Variant, b As Variant, 
filename As Variant
    filename = "c://1.jpg"
    Call st.split2rgb(5, h, w, r, g, b, filename)  
可见matlab下函数的输入输出参数在com组件里全是variant型的变量,测试大获成功,结

果就跟matlab下运行的一摸一样,爽

2.c#.net
下实现调用
    
打开或新建一个c#项目(我采用的是vs.net编辑器),选中右边的解决方案资源管理器
中的引用,点鼠标右键,选添加引用,在弹出来的窗口中选com,然后也找到comtest_1_0
.dll
,点选择,然后确定就可,此时此com组件也添加到工程里面去了,同样我们可以选择

对象浏览器来看comtest及下面的sgltest类,c#测试项目如下:
    
测试im_test方法的代码
:
    comtest.sgltestClass st=new comtest.sgltestClass();                        
    st.im_test();
    
测试split2rgb方法的代码
:
    comtest.sgltestClass st=new comtest.sgltestClass();                        
    object h=null,w=null,r=null,g=null,b=null;
    object filename="c://1.jpg";
    st.split2rgb(5,ref h,ref w,ref r,ref g,ref b,filename);
可见输入参数是ref object型的,而输出参数是object型的,测试同样大获成功,与
matl
ab
下运行的结果一摸一样,爽呆了。

--
 come on,baby!


※ 
修改:·xxhn  May 21 10:27:53 修改本文·[FROM:   202.113.39.83]
※ 
来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools       
  : matlabcombuilder系列-vc下调用

发信站: BBS 水木清华站 (Wed May 21 10:25:17 2003)

这一部分讲vc下实现调用第一部分我们生成的comtest_1_0.dll,同样要记得先对
mwcomut
il.dll
进行注册(怎么注册参看第一部分)vb.net下实现对com组件的调用很简单,而
v
c
下实现这一步我可是摸索了好几天(主要是vc用的不好
)
1.
先做一些准备工作,用ole viewer工具

    
开始--程序--Microsoft visual studio6.0--Microsoft visual studio6.0 Tools--
OLE viewer(
这个工具也可以通过在vc下点Tools--OLE/COM Object Viewer来打开,在
Ole
 viewer
工具里,在右边选择Type libraries,将他展开,找到
comtest 1.0 Type Library
,选中它,点鼠标右键,选view,便又弹出一窗口,点工具栏上的save按钮,分别将他保

存为comtest_1_0.h,comtest_1_0.c(也可以存为comtest_1_0.Idl接口文件),我们就可以通
过这两个文件实现对comtest_1_0.dll调用

2.vc
下调用
    
新建或打开一个vc工程,注意,此时不用对编译器进行任何设置(而用mcc生成的dll
们么设置一大堆,我这儿只设置了Precomplied headers,Automatic use of precomplied
 headers,
写上 stdafx.h),comtest_1_0.hcomtest_1_0.c加入工程,并复制

一个comtest_1_0.dll到工程目录下,由于comtest_1_0.dll还要用到mwcomutil.dll,所
以将<matlabroot>/extern/include/下的mwcomutil.hmwcomtypes.h也加入工程
(
将这两个文件拷贝入工程路径下,如果设置了library path,可以不加)
此时可以通过classView看到多出了_IIDIMWUtil,Isgltest类,Isgltest就是我们在
mat
lab
下建起来的sgltest

vc
下代码如下
//
这几个是引入dll和头文件
#import "mwcomutil.dll"
#import "comtest_1_0.DLL"
#include "mwcomutil.h"
#include "comtest_1_0.h"
#include "comutil.h"       //
此文件是用来处理由char *VARIANT类型的转换
测试im_test方法的代码:
   if(FAILED(CoInitialize(NULL)))      //
初始化调用
com
   {
     AfxMessageBox("unable to initialize COM");
   }
   Isgltest *st=NULL;   
   //
创建一个com组件,CLSID_sgltestIID_Isgltest可以从comtest_1_0.h
comtest_
1_0.c
里找到

   HRESULT hr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi
d **)&st);
   if(SUCCEEDED(hr))
   {
       st->im_test(); 
       AfxMessageBox("succeed");
           st->Release();
   }
   else
   {
       AfxMessageBox("unsucceed");
   }    
如果你的vc工程是console project的话,上述的AfxMessageBox可改成printfcout
测试split2rgb方法的代码(类型转换我参照visual c的精华区也转换成功了)
   if(FAILED(CoInitialize(NULL)))
   {
     AfxMessageBox("unable to initialize COM");
   }
   Isgltest *st=NULL;   
   HRESULT hr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi
d **)&st);
   VARIANT m,n,r,g,b,filename;
   VariantInit(&m);
   VariantInit(&n);
   VariantInit(&r);
   VariantInit(&g);
   VariantInit(&b);
   VariantInit(&filename);
   filename.vt=VT_BSTR;
   filename.bstrVal=_com_util::ConvertStringToBSTR("C://1.jpg");
   if(SUCCEEDED(hr))
   {
       st->split2rgb(5,&m,&n,&r,&g,&b,filename);
       st->Release();
       AfxMessageBox("succeed");
   }
   else
   {

       AfxMessageBox("unsucceed");
   }    
同样,运行结果与matlab下的结果一摸一样,记得我们的im_test里面可是使用了imshow

,以前用mcc生成的程序中用它可是有错哦,爽呆了。
关于VC下用com组件及其类型的转变请参看msdn及其Visual C的精华区
--
 come on,baby!


※ 
修改:·xxhn  May 21 10:36:09 修改本文·[FROM:   202.113.39.83]
※ 
修改:·xxhn  May 21 20:23:21 修改本文
·[FROM:   202.113.39.83]
※ 
修改:·xxhn  May 23 19:12:04 修改本文
·[FROM:   202.113.39.16]
※ 
来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

发信人: xxhn (小湖南), 信区: MathTools       
  : matlabcombuilder系列-打包及其优缺点评注

发信站: BBS 水木清华站 (Wed May 21 10:25:42 2003)

 ^_^
combuilder系列可以结尾了

.打包:
    
matlab下的workspace里打comtool,点file-open project将我们先前建好的
comte
st.cbl
工程文件打开,再点component--package component就实现了打包,此时到

comtest/distrib
文件夹里看,生成的comtest.exe就是打包后
的解压程序,双击它会解压出一些文件,再点击解压出来的_install.bat就可以实现安装
(
按他的步骤去做就行了)

.优缺点评注

    
这几天用这个combuilder可把我给爽死了,特别是在vc下调用成功时,记得精华区里
曾讲combuilder没有什么实质性的突破,我可不这么认为,它的突破可大了
    1.
做出来的是com,通用的,任何编译器只要支持com,就可以实现调用,想c++ build
er,Delphi
等的,我想只要按照调用com组件去做,也能成功的

    2.
支持imshow等一些原来混编用不了的函数,对图形库的支持也比以前强(这些还需各
位大侠共同测试)
    3.
实现方法简单,没有像以前混编还要设置一大堆东东

    4.
能够在matlab下写自己的类,并为自己的类编写成员、方法和事件,管理工程也方
便(这个有点像vcvb下管理工程一样)
    
用的太爽了,一下子还不知道怎么写缺点了,^0^,我想缺点还需大家一起用来找出

    
我这儿说一个缺点,感觉它的参数全是VARIANT型的,不怎么方便
--
 come on,baby!


※ 
修改:·xxhn  May 21 10:29:04 修改本文·[FROM:   202.113.39.83]
※ 
来源:·BBS 水木清华站 http://smth.org·[FROM: 202.113.39.83]

 

发信人: capriccio (), 信区: MathTools       
  vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Thu May 29 23:22:28 2003), 转信

用一个例子说明一下,
首先用matlabm文件描述一下例子中com组件的功能:
function y=hehe(x)
y=x*2;
把该文件保存为hehe.m

combuilder中建立工程comparatest,加入类paratest

然后加入文件hehe.m,build成为com组件。

下面是vc中的代码:
#include "stdafx.h"
#include "stdio.h"
#import "mwcomutil.dll"
#import "comtest2_1_0.DLL"
#include "mwcomutil.h"
#include "comtest2_1_0.h"

#include "comutil.h"    

int main(int argc, char* argv[])
{
        double a[4]={1,2,3,4};
        int i=4;
        if(FAILED(CoInitialize(NULL)))  //
初始化调用com
        {
         printf("unable to initialize COM");
        }
        VARIANT x,y;
        VariantInit(&x);
        VariantInit(&y);
        x.vt=VT_R8|VT_ARRAY;//
声明x的类型为VT_ARRAY

                        //Array
中的元素为double
        SAFEARRAYBOUND rgsabound[1];
        rgsabound[0].cElements=4;//
元素的个数
        rgsabound[0].lLbound=0;  //
矩阵索引的下界
        x.parray=SafeArrayCreate(VT_R8,1,rgsabound);//
该函数新建
                        //
一个SafeArray,并把这个SafeArray的描述
                        //
符的指针传给x.parray
        x.parray->pvData=a;
        Iparatest *st=NULL;
        //
创建一个com组件,CLSID_paratestIID_Iparatest可以从
        //comparatest2_1_0.h
comparatest2_1_0.c里找到
        HRESULT hr=CoCreateInstance(CLSID_paratest,NULL,CLSCTX_ALL,
                                 IID_Iparatest,(void **)&st);
        if(SUCCEEDED(hr))
        {
                st->hehe(1,&y,x);
                memcpy(a,y.parray->pvData,4*sizeof(double));
                //
matlab文件中返回的矩阵y是实数行的时候,com组件
                //
把得到的y的值存放再y.parray->pvData所指向的内存区域。
                printf("%f/n%f/n%f/n%f/n",a[0],a[1],a[2],a[3]);
                printf("succeed");
                st->Release();
        }
        else
        {
                printf("unsucceed");
        }
        return 0;
}

上面的方法解决了实矩阵参数在com组件和vc之间的传递,应该也能用到其他
类型的矩阵,比如字符和整型的矩阵。但是如果com组件是由matlab combuilder
编译m文件得到的,而且m文件所返回的矩阵是复数型的,就不行了。因为好像

这时返回的矩阵并不是如上所述保存在y.parray中,至于到底保存在什么地方
就有待于大牛们把它找出来了,反正俺琢磨了一整天也没有一点头绪:(

--

※ 
来源:·BBS 水木清华站 smth.org·[FROM: 166.111.33.68]

发信人: xxhn (小湖南), 信区: MathTools
  : Re: MatlabVC混合编程中出现的问题(idldll来调用
)
发信站: BBS 水木清华站 (Tue Aug 19 15:08:50 2003), 转信


这儿再提供一种通过Idldll来调用com组件的方法(不用生成*.h*.c文件)
其实这种方法比通过生成.h.c文件来调用要简单一些:),还用精华区的例子

1.
通过ole/com object生成idl文件,将此idl文件加入工程,点菜单build-complie 
comtest_1_0.tlb,
生成tlb文件

2.
打开classwizard,点右边的add class-from a type library class,选中刚生成的
comtest_1_0.tlb(
应该在debug/目录下),其实这儿也可以直接选择用matlabcombuilder
生成的comtest_1_0.dll(这样就省去了第一步),后面将出现生成class的一些对话框,照

提示去做就可以了,这样就生成了comtest_1_0.hcomtest_1_0.cpp,多了一个Isgltest
:)
3.
测试代码如下
:
头文件中只需添加
:
#include "comtest_1_0.h"
测试代码
:
   Isgltest st;
   AfxOleInit();
   if(st.CreateDispatch(_T("comtest.sgltest")))
      {
         st.im_test();    
         AfxMessageBox("Haha,Succeeded");
         st.ReleaseDispatch();
      }
   else
         AfxMessageBox("UnSucceeded");

上述代码的具体意义参看msdn,我也是刚刚摸索到
:)

  promise0608 (promise0608) 的大作中提到

我在使用COM组件时,用Microsoft Visual Studio的工具OLE Viewer 打开生成的组件。找
到那个用Matlab com builder生成的Dll文件,将其另存为*.h *.c 文件时,出现错误!
我用的是VC.NET,不知道什么原因!
请大家帮帮我!
谢谢了!


--
 come on,baby!


※ 
修改:·xxhn  Aug 19 15:12:28 修改本文·[FROM:   218.76.251.27]
※ 
来源:·BBS 水木清华站 smth.org·[FROM: 218.76.251.27]

 

发信人: xxhn (小湖南), 信区: MathTools       
  : Re: vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Fri May 30 12:58:02 2003), 转信

我再来补充一下,vb,.net中的数组和com中的VARIANT变量的相互转换
vb.net变量的相互转换也很简单,下面举例简单说一下:
在我们前面的sgltest里面增加一个函数叫y=paratest(x),x,y为输入输出,都为矩阵
1.vb
:
Dim st As sgltest
Set st = New sgltest
Dim x(2) As Variant, y As Variant
x(0) = 3#
x(1) = 5#
x(2) = 6#
Call st.paratest(1, y, x)
y(1,0),y(1,1),y(1,2)
就是输出的数组

2..net
:
comtest.sgltestClass st=new comtest.sgltestClass();
object y=null;
object[] x;
x=new Object[3];
x[0]=2.0;
x[1]=3.0;
x[2]=4.0;
pt.para_test(1,ref y,x);
y[0,0],y[0,1],y[0,2]
就是输出的数组



  capriccio (的大作中提到
用一个例子说明一下,
首先用matlabm文件描述一下例子中com组件的功能:
: function y=hehe(x)
: y=x*2;
把该文件保存为hehe.m
combuilder中建立工程comparatest,加入类paratest
然后加入文件hehe.m,build成为com组件。
下面是vc中的代码:
: #include "stdafx.h"
: #include "stdio.h"
: #import "mwcomutil.dll"
: ...................

--
 come on,baby!


※ 
来源:·BBS 水木清华站 smth.org·[FROM: 202.113.40.70]

发信人: capriccio (), 信区: MathTools       
  : Re: vc中的数组和com中的VARIANT变量的相互转换

发信站: BBS 水木清华站 (Fri May 30 14:49:09 2003), 转信

关于传递的参数是复数矩阵的问题,
郁闷了好长时间之后突然想到,
没有必要非要搞清楚这个问题(虽然matlab的确提供了复数参数的传递方法)
只需要把复数的实部和虚部作为两个实数参数分别传递就行了。

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

发信人: xxhn (小湖南), 信区: MathTools       
  : Re: 关于com builder一问!

发信站: BBS 水木清华站 (Fri May 30 19:35:07 2003), 转信


  siciliner (fisher) 的大作中提到
  : Re: 关于com builder一问!
发信站: BBS 水木清华站 (Fri May 30 15:28:10 2003), 转信

没有人帮帮俺么?

  siciliner (fisher) 的大作中提到
: : 6.5信有的com builder做了一下测试,发现如果没有调有simulink模型,也就是m文件
: : 里面不包含sim命令,用combuilder建立com组件不会出现问题,但是如果含有sim命令,
: : 就会出错
: : 请教各位,有没有什么好的解决办法,还是combuilder不支持simulink
                                      ~~~~~~~
我想就是这个原因,如下是从matlab
combuilder
的帮助中摘下来的

Limitations and Restrictions
In general, limitations and restrictions on the use of MATLAB COM Builder ar
e the same as those for the MATLAB Compiler. See the Limitations and Restric
tions section of the MATLAB Compiler User's Guide for details. Note that alt
hough the Compiler supports some usage of the MATLAB input command, MATLAB C
OM Builder does not support this command at all.
matlab compiler不支持simulink,所以combuilder也不支持吧


: : 多谢了!


: --

: ※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.73.158]


--
 come on,baby!


※ 
来源:·BBS 水木清华站 smth.org·[FROM: 202.113.40.70]

 

.combuilder与vc混编中复数类型的输出(By LPCTSTR)

今天瞎捣鼓了一下,在前辈们的基础上解决了这个问题 ;)

调用com的方法和前面的几位略有不同,个人感觉比他们的简单、正规一点;)

step 1 建立m文件,build成com

m文件写的很简单

function cplx = getcplx()

cplx = 1+2i

方便后面看代码,写出我建立com工程时组建名称:AMyCom 类:MyTst

step 2 导出必要的头文件

1.打开OLE viewer (vc6.0菜单:tools--〉OLE/COM Object Viewer

2.OLE viewer 菜单:file-->view TypeLib

3.打开combuilder生成的dll:AMycom_1_0.dll

4.File-->save as 选择生成 .h文件

5.将生成的头文件拷到vc工程路径下

6.重复以上步骤生成mwcomutil.dll的头文件

step 3 vc下的简单测试源代码如下:

#include <windows.h>

#include "stdio.h"

#include "mwcomutil.h"

#include "Amycom_1_0.h"

void main()

{

CoInitialize(NULL); //初始化com

//创建Com实例

CLSID CLSID_MyTst;

CLSIDFromProgID(L"AMyCom.MyTst.1_0",&CLSID_MyTst);

//这里的ProgID可以在combiulder的component->component info里面看到


邓科峰 dkf03@mails.tsinghua.edu.cn

//或者搜索注册表得到

IID IID_IMyTst = __uuidof(IMyTst);

IMyTst* pMyTst = NULL;

CoCreateInstance(CLSID_MyTst,NULL,CLSCTX_ALL,IID_IMyTst,(void**) &pMyTst

);

VARIANT r[5];

for (int i=0; i<5; i++)

{

VariantInit(&r[i]);

}

pMyTst->getcplx(1,&r[0]); //调用函数接口

IMWComplex* pTemp = (IMWComplex*)r[0].pdispVal;//复数类型的接口

pTemp->get_Real(&r[1]);

pTemp->get_Imag(&r[2]);

double dr = r[1].dblVal; //获取实部

double img = r[2].dblVal; //获取虚部

printf("real : %f/nimg : %f/n",dr,img); //

getchar();

CoUninitialize();

return;

}

个人感觉matlab的一部分比较复杂的数据类型都做成了com组建封装在mwcomutil.dll中,当

OLE viewer打开该文件时可以看到好多接口,其中包括IWMComplex即复数类型的接口,co

m参数的传递通过VARIANT类型来实现,可以在MSDN上查到详尽的用法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值