Archive for February, 2007

Basic usages of TinyXML

昨天根据TinyXML的docs,学习了一些基本的用法。TinyXML相对于Xerces来说,接口更加简洁,好理解。虽然MS XML Parser也不错,但对于需要跨平台部署的应用程序,是不适合的。

CString strMsg;
TiXmlDocument doc("demotest.xml");
bool loadOK = doc.LoadFile();
if (!loadOK)
strMsg.Format("Could not Load. [%s]\n", doc.ErrorDesc());
else
strMsg.Format("OK\n");
TiXmlHandle sectHandle(&doc);
// 修改第2个Item节点的TEXT值
sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 1).Child(0).Text()->SetValue("Some Value");
// 修改的3个Item节点的distance属性
sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 2).Element()->SetAttribute("distance", "so near");
// 修改第1个Item节点的名字
sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 0).Element()->SetValue("Other Item");
// 取得第1个Item节点的TEXT值
strMsg.Format("%s", sectHandle.ChildElement("ToDo", 0).ChildElement("Other Item", 0).Element()->GetText());
// 取得第2个Item的节点名字
strMsg.Format("%s", sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 1).Element()->Value());
// 取得第3个Item节点的distance属性
strMsg.Format("%s", sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 2).Element()->Attribute("distance");
// 取得第3个Item节点的priority属性
int n=0;
sectHandle.ChildElement("ToDo", 0).ChildElement("Item", 2).Element()->Attribute("priority", &n);
AfxMessageBox(strMsg, MB_OK, 0);
doc.SaveFile();

XML文件的结构:

<?xml version=”1.0″ standalone=”no” ?>
<!– Our to do list data –>
<ToDo>
<!– Do I need a secure PDA? –>
<Item priority=”1″ distance=”close”>Go to the
<bold>Toy store!</bold>
</Item>
<Item priority=”2″ distance=”none”>test</Item>
<Item priority=”2″ distance=”far & back”>Look for Evil Dinosaurs!</Item>
</ToDo>

Leave a Comment

error LNK2001: unresolved external symbol ___argv

今天写一个小程序,在代码里面加了CxImage,链接的时候报错”error LNK2001: unresolved external symbol ___argv”,还有其他一堆外部符号,后来参考这个网页,加入了_AFXDLL符号,链接成功。

Leave a Comment

Embed SpiderMonkey in your code

SpiderMonkeyMozilla下的一个开源项目,是用来解析和运行JavaScript脚本的,分JAVA和C两种实现版本。为了能让自己的程序更加灵活和易扩展,加入脚本支撑是一个非常有效的方式。今天尝试了一下把SpiderMonkey加入到自己的程序中,运行了一个简单的脚本。

下载获得js-1.60.tar.gz的tarball并解压,用vc6打开src下的js.mdp,vc6会提示你转换到新版的dsp,然后设定Active Project为win32 release,build,稍等一会就在release目录下得到js32.dll和js32.lib,把这两个文件以及src下的*.h,复制到你的应用程序目录下(或者直接设定你的Project的搜索路径也行)。

附测试代码:
#include <stdio.h>
#define XP_WIN
#include "jsapi.h"
#pragma comment(lib, "js32.lib")

//---------------------------------------------------------------------------
static JSBool my_abs(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
{
  jsdouble x, z;
  if (!JS_ValueToNumber(cx, argv[0], &x)) return JS_FALSE;
  z = (x<0) ? -x : x;
  return JS_NewDoubleValue(cx, z, rval);
}
static JSFunctionSpec my_functions[] = {
  { "abs", my_abs, 1},{0}
  };

char* VersionToString(JSVersion v)
{
  switch(v) {
  case JSVERSION_1_0: return "JavaScript 1.0";
  case JSVERSION_1_1: return "JavaScript 1.1";
  case JSVERSION_1_2: return "JavaScript 1.2";
  case JSVERSION_1_3: return "JavaScript 1.3";
  case JSVERSION_1_4: return "JavaScript 1.4";
  case JSVERSION_ECMA_3: return "ECMA 262 Edition 3";
  case JSVERSION_1_5: return "JavaScript 1.5";
  case JSVERSION_DEFAULT: return "Default JavaScript Version";
  case JSVERSION_UNKNOWN: return "Unknown JavaScript version";
  default: return "Unknown JavaScript version";
  }
}
int main()
{
  JSVersion version; // 版本号
  JSRuntime *rt; // 运行时的内存空间
  JSContext *cx; // 环境句柄
  JSObject *glob, *it; // 对象(函数,类等)
  JSBool builtins;
  // 全局对象
  JSClass global_class = {
  "global",0,
  JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,
  JS_EnumerateStub,JS_ResolveStub,JS_ConvertStub,JS_FinalizeStub
  };
  rt = JS_NewRuntime(8L * 1024L * 1024L);
  if (!rt) return 1;
  cx = JS_NewContext(rt, 8192);
  if (cx == NULL) return 1;
  version = JS_GetVersion(cx);
  printf("Script Version: %s", VersionToString(version));

glob = JS_NewObject(cx, &global_class, NULL, NULL);
  builtins = JS_InitStandardClasses(cx, glob);

JS_DefineFunctions(cx, glob, my_functions);
  //JS_DefineFunction(cx, glob, "abs", my_abs, DOIT_MINARGS, 0);

  // FILE *fp = fopen("hello.js", "rb");
  // char szScript[512];
  // fread(buff, 1, 510, fp);
  // fclose(fp);
  char* szScript = "var today=Date(); today.toString(); var n=2001; n=n+1; var a=-305; abs(a);";
  jsval rval;
  JSString *str;
  char* pFileName = NULL;
  int nLines = 0;

if (JS_EvaluateScript(cx, glob, szScript, strlen(szScript), pFileName, nLines, &rval) == JS_FALSE) {
  printf("Error Occured while Run Script Engine.\n");
  return 1;
  }
  str = JS_ValueToString(cx, rval); // rval返回脚本最后执行的那个变量的值
  printf("Script Result: %s\n", JS_GetStringBytes(str));

JS_DestroyContext(cx);
  JS_DestroyRuntime(rt);
  JS_ShutDown();
  return 0;
}

//---------------------------------------------------------------------------
注:
如果需要让调试器跟踪进如SpiderMonkey的源代码,需要生成debug版的js32.dll和js32.lib。
参考链接:
How to Embed JS Engine.
JavaScript C Engine Embedder’s Guide.
下载地址:
http://ftp.mozilla.org/pub/mozilla.org/js/

Leave a Comment

Using WinPcap in C++ Builder

几天前,有个朋友跟我探讨怎么从网卡上抓数据包,找了找资料,发现了WinPcap库。WinPcap是unix下libpcap的windows版,它是从TCP/IP协议的连接层抓包,工业标准级的开源库。

下载和安装都很容易,先找了一个Example下的例子编译,发现有COFF和OMF的问题,C++Builder不支持VC的COFF格式的LIB,先用BCB自带的coff2omf转换

coff2omf -v -lib:ms wpcap.lib wpcap_o.lib
coff2omf -v -lib:ms Packet.lib Packet_o.lib

再编译链接就OK了。

Comments (4)

Ansi C++ keyword extensions implemented in C++ builder

虽然用C++builder也好长时间了,但从来没有思考,为什么要实现非标准的关键字。

前两天看到一则讨论,说是否要在Java里面加入Closure,跟帖的人里面就有人拿C++Builder来举例。于是我翻翻C++Builder的帮助,看到了下面四个扩展关键字。

__classid,主要是用来通过类名获取类的TMetaClass,而TMetaClass是某个C++类在Object Pascal中的表现形式,因为C++Builder是架构在Object Pascal上的。这个关键字用得最多的地方,莫过于当要创建一个窗体的时候了,Application->CreateForm()的第一个参数,一般都是__classid(TSomeForm)的形式。

 __closure,主要用来定义一个类的成员函数的类型。有了__closure定义的类成员函数,就可以被赋值给另一个类中定义的函数指针变量。听起来有点拗口,实际上就是C++Builder中各个组件所具有的事件的实现方式。自己封装过组建的程序员对此应该非常熟悉。

 __property,这个也许是实际写代码用的最多的了。用来定义一个类的属性,其实在JAVA和C#中都有属性的概念,而且实现起来非常容易。尽管C++Builder把它扩充了,但写起代码来还是稍显繁琐。

__published,没什么好说的,用来定义一个在IDE环境中通过OBJECT INSPECTOR显示出来的类成员。

如果__property的实现手法再简洁一点(像C#那样),就完美了。不知道C++标准组织会不会在未来发布新版C++时,考虑加入这些特性。

——–
附一个bcb中__closure用法的示例:

typedef void __fastcall (__closure*THelloEvent)(char*);class TMyObject
{
private:
  THelloEvent m_OnHello;
protected:

public:
  TMyObject() { }
  ~TMyObject() { }
  void SetHello(THelloEvent handler) { m_OnHello = handler; }
  THelloEvent GetHello() { return m_OnHello; }
  virtual void ExecuteHello(char* msg) { m_OnHello(msg); }
};

class TMyComponent
{
private:
  TMyObject* m_Object;
public:
  TMyComponent() { m_Object = new TMyObject(); }
  ~TMyComponent() { delete m_Object; }
  void __fastcall SayHi(char* msg) { cout << msg << endl; }
  void ChangeFun() { m_Object->SetHello(SayHi); }
  TMyObject* GetObject() { return m_Object; }
};

int main(int argc, char* argv[])
{
  TMyComponent d;
  d.ChangeFun();
  d.GetObject()->ExecuteHello("Hi, world");
  system("pause");
  return 0;
}

Comments (1)