前几天被人问起这个问题:怎么在C语言中使用MSXML。本来以为蛮简单的,因为C语言里也支持指针和结构,代码没什么地方需要改的,结果发现不然……

先来看一下C++里是怎么写的:

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
#import "msxml6.dll" raw_interfaces_only

#include <cstdio>
using namespace std;

#include "windows.h"

int main(){
    CoInitialize(NULL);

    MSXML2::IXMLDOMDocument2* doc = NULL;
    CoCreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER, __uuidof(MSXML2::IXMLDOMDocument2), (LPVOID*)&doc);

    VARIANT_BOOL result;
    doc->loadXML(_bstr_t(L""), &result);

    BSTR outxml = NULL;
    doc->get_xml(&outxml);

    wprintf(L"xml = %s\n", outxml);

    ::SysFreeString(outxml);
    doc->Release();

    CoUninitialize();

    return 0;
}

这里为了简洁,直接引用了”windows.h”,并且没有检查函数的返回值。

代码里一些东西是C语不支持的:

  • 预编译指令#import
  • 命名空间(Namespace),当然这个不是很重要
  • 关键字__uuidof也不支持
  • 实际上doc->Release()这样的函数调用也不是支持的,详见下面的代码

于是在C语言中就变成了这样:

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
#define COBJMACROS
#include "msxml6.h"

#include "windows.h"
#include "stdio.h"

int main(){
    IXMLDOMDocument2 *doc;
    VARIANT_BOOL loaded;
    BSTR inxml = SysAllocString(L"");
    BSTR outxml = NULL;

    CoInitialize(NULL);
    CoCreateInstance(&CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc);
    IXMLDOMDocument_loadXML(doc, inxml, &loaded);
    IXMLDOMDocument_get_xml(doc, &outxml);

    wprintf(L"XML = %s\n", outxml);

    SysFreeString(inxml);
    SysFreeString(outxml);
    IXMLDOMDocument_Release(doc);

    CoUninitialize();

    return 0;
}

最大的改动是定义了COBJMACROS,这样可以使用另外一种的函数调用,比如原来的doc->get_xml(&outxml);变成了IXMLDOMDocument_get_xml(doc, &outxml);,实际上IXMLDOMDocument_get_xml(a,b)是一个宏,它会被展开成a->vtbl->get_xml(a,b)。至于COBJMACROS具体是什么意思,我也没找到文档-_-

不过无论如何,在C语言中是可以使用MSXML的,并且和C++中没什么大区别……

 

批处理指令中并没有原生支持数组,但这不代表不能模拟出来。

来看下面的代码:

1
2
3
4
5
6
7
SET Obj_Length=2

SET Obj[0].Name=Test1
SET Obj[0].Value=Hello World

SET Obj[1].Name=Test2
SET Obj[1].Value=blahblah

这样就定义了一个数组了,而且是结构体的数组。

在需要取值的时候,可以这么玩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SET Obj_Index=0

:LoopStart
IF %Obj_Index% EQU %Obj_Length% GOTO :EOF

SET Obj_Current.Name=0
SET Obj_Current.Value=0

FOR /F "usebackq delims==. tokens=1-3" %%I IN (`SET Obj[%Obj_Index%]`) DO (
    SET Obj_Current.%%J=%%K
)

ECHO Name = %Obj_Current.Name%
ECHO Value = %Obj_Current.Value%
ECHO.

SET /A Obj_Index=%Obj_Index% + 1

GOTO LoopStart

输出结果:

Name = Test1
Value = Hello World

Name = Test2
Value = blahblah

怎么样,很不错吧~~

© 2004 - 2011 Leona+Suffusion theme by Sayontan Sinha