编译Wkhtmltopdf

1、首先下载源码

git clone https://github.com/wkhtmltopdf/wkhtmltopdf.git  D:\GitHub\wkhtmltopdf
git clone https://github.com/wkhtmltopdf/qt.git  D:\GitHub\wkhtmltopdf\qt

2、安装下面几个软件
VS2013
Python2.7
ActivePerl
NSIS

3、初始化环境变量

set GIT_HOME=C:\Program Files\Git
set NSIS_HOME=C:\NeoLanguages\NSIS
set PYTHON_HOME=C:\NeoLanguages\Python27_x86
set PERL_HOME=C:\NeoLanguages\Perl
set PATH=%GIT_HOME%\bin;%PYTHON_HOME%;%PERL_HOME%\bin;%NSIS_HOME%;%PATH%
@call C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat x86

4、编译

python scripts\build.py msvc2013-win32

PS:
如果编译失败,一般是由于依赖包的网站无法方位导致的,你懂的。
这个时候,打开build.py文件,找到DEPENDENT_LIBS,自备梯子,下载后直接放到static-build路径下就好了。

posix_memalign函数在Windows下的实现

posix_memalign函数主要用于申请内存时,做内存对齐使用,Windows下对应的函数为_aligned_malloc,但两者的参数有一定区别:

int posix_memalign(void **memptr, size_t alignment, size_t size);
void * _aligned_malloc(size_t size, size_t alignment);

从stackoverflow上,找到了两种实现方式,对于第一种,我只能说,佩服佩服。

1、最简练的实现方式

#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)

2、比较稳妥的实现方式

#ifdef _WIN32
static int check_align(size_t align)
{
    for (size_t i = sizeof(void *); i != 0; i *= 2)
    if (align == i)
        return 0;
    return EINVAL;
}
 
int posix_memalign(void **ptr, size_t align, size_t size)
{
    if (check_align(align))
        return EINVAL;
 
    int saved_errno = errno;
    void *p = _aligned_malloc(size, align);
    if (p == NULL)
    {
        errno = saved_errno;
        return ENOMEM;
    }
 
    *ptr = p;
    return 0;
}
#endif

CPP实现CORBA静态绑定(八)

  • CORBA基本架构
  • IDL文件编写
  • CPP示例实现(上)
  • CPP示例实现(下)
  • C示例实现(IOR+NS上)
  • C示例实现(IOR+NS下)
  • C示例实现(IOR上)
  • C示例实现(IOR下)

然后完成客户端部分:
Hi-client-ior.c

#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <orbit/orbit.h>
 
#include "Hi.h"
 
/*
Usage: ./hi-client_ns
*/
 
/**
 * test for exception
 */
static
gboolean
raised_exception(CORBA_Environment *ev)
{
    return ((ev)->_major != CORBA_NO_EXCEPTION);
}
 
/**
 * in case of any exception this macro will abort the process
 */
static
void
abort_if_exception(CORBA_Environment *ev, const char* mesg)
{
    if (raised_exception (ev)) {
        g_error ("%s %s", mesg, CORBA_exception_id (ev));
        CORBA_exception_free (ev);
        abort();
    }
}
 
 
/*
 * main
 */
int main(int argc, char* argv[])
{
    CORBA_ORB orb=CORBA_OBJECT_NIL;
    CORBA_Environment ev;
    HiCorba_Hi service = CORBA_OBJECT_NIL;
 
    //init orb
    g_print("\nClient>starting client...");
    g_print("\nClient>creating and initializing the ORB");
    CORBA_exception_init(&ev);
    abort_if_exception(&ev, "CORBA_exception_init failed");
    orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
    abort_if_exception(&ev, "CORBA_ORB_init failed");
 
    // read name_service ior from ns.ior
    CORBA_char  filename[] = "service.ior";
    FILE *file   = NULL;
    g_print("\nClient>reading the file '%s'",filename);
    if ((file=fopen(filename, "r"))==NULL)
                g_error ("could not open '%s'", filename);
    gchar objref[1024];
    fscanf (file, "%s", &objref);
    g_print("\nClient>getting the 'IOR' - from the file '%s'",filename);
    g_print("\nClient>the IOR is '%s'",objref);
        service = (HiCorba_Hi)CORBA_ORB_string_to_object(orb,objref,&ev);
    abort_if_exception(&ev, "CORBA_ORB_string_to_object 'NameService IOR' failed");
 
    // invoke service
    g_print("\nClient>calling the Hi service...");
    CORBA_char *msg=HiCorba_Hi_sayHiTo(service, "neohope", &ev);
    abort_if_exception(&ev, "HiCorba_Hi_sayHiTo failed");
        g_print("\nClient>server returned the following message: %s\n", msg);
 
    CORBA_Object_release(service, &ev);
    abort_if_exception(&ev, "release failed");
 
        if (orb != CORBA_OBJECT_NIL)
        {
           /* going to destroy orb.. */
           CORBA_ORB_destroy(orb, &ev);
       abort_if_exception(&ev, "destroy failed");
    }
 
}

MakeClient

CC       = gcc
CFLAGS   = -c -g -pthread -D_REENTRANT -DORBIT2=1 \
           -I/usr/include/orbit-2.0 \
           -I/usr/include/glib-2.0 \
           -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDFLAGS  = -Wl,--export-dynamic -lORBit-2 -lORBitCosNaming-2 -lgmodule-2.0 \
           -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm \
           -L/usr/lib
ORBIT_IDL= /usr/bin/orbit-idl-2
 
all : Hi-client-ior.bin
 
Hi-client-ior.bin : Hi-common.o Hi-stubs.o Hi-client-ior.o
    $(CC) $(LDFLAGS) Hi-common.o Hi-stubs.o Hi-client-ior.o -o Hi-client-ior.bin
 
%.o : %.c
    $(CC) $(CFLAGS) $< -o $@
 
nidl : Hi.idl
    $(ORBIT_IDL) Hi.idl
    $(ORBIT_IDL) --skeleton-impl Hi.idl
 
clean:
    rm -rf *.bin
    rm -rf *.o

编译

Make -f MakeClient

运行

#首先运行orbd
orbd -ORBInitialPort 1900
  
#然后运行server
./Hi-server-ior.bin
Server>starting server...
Server>creating and initializing the ORB
Server>getting reference to RootPOA
Server>activating the POA Manager
Server>creating the servant
Server>writing the file 'service.ior'
Server>writing the IOR to file 'service.ior'
Server>running the orb...
Server>server is returning: Hi, neohope !
  
#然后运行client
./Hi-client-ior.bin
Client>starting client...
Client>creating and initializing the ORB
Client>reading the file 'service.ior'
Client>getting the 'IOR' - from the file 'service.ior'
Client>the IOR is 'IOR:010000001300000049444c3a4869436f7262612f48693a312e300000030000000054424f580000000101020005000000554e4958000000000a0000006c6f63616c686f73740000002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d316235362d302d376663653334336261303164360000000000000000caaedfba58000000010102002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d316235362d302d37666365333433626130316436000000001c00000000000000dbcce0b85e73a828c02b2828282828280100000060aa3a1a01000000480000000100000002000000050000001c00000000000000dbcce0b85e73a828c02b2828282828280100000060aa3a1a01000000140000000100000001000105000000000901010000000000'
Client>calling the Hi service...
Client>server returned the following message: Hi, neohope !

CPP实现CORBA静态绑定(七)

  • CORBA基本架构
  • IDL文件编写
  • CPP示例实现(上)
  • CPP示例实现(下)
  • C示例实现(IOR+NS上)
  • C示例实现(IOR+NS下)
  • C示例实现(IOR上)
  • C示例实现(IOR下)

在linux系统下,有很多开源的CORBA通讯框架,在C的示例中,使用了orbit的框架。
如我用的是Debian系统,可以直接安装:

apt-get install orbit2
apt-get install liborbit2-dev

安装后,可以通过工具orb-rdl-2从idl文件生成需要的stubs及skeletons接口代码:

#该命令会生成文件:Hi.h、Hi-common.c、Hi-skels.c、Hi-stubs.c
orbit-idl-2 Hi.idl

可以通过工具orb-rdl-2从idl文件生成服务端代码:

#该命令会生成模板文件:Hi-skelimpl.c
orbit-idl-2 --skeleton-impl Hi.idl

首先完成服务端部分:
Hi-server-ior.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>
#include "Hi.h"
#include "Hi-skelimpl.c"
/*
./Hi-server_ns -ORBInitRef NameService=[string of IOR of NameService]
*/
 
/**
 * test for exception
*/
static
gboolean
raised_exception(CORBA_Environment *ev) {
    return ((ev)->_major != CORBA_NO_EXCEPTION);
}
 
/**
 * in case of any exception this macro will abort the process
*/
static
void
abort_if_exception(CORBA_Environment *ev, const char* mesg)
{
    if (raised_exception (ev)) {
        g_error ("%s %s", mesg, CORBA_exception_id (ev));
        CORBA_exception_free (ev);
        abort();
    }
}
 
/*
 * main
*/
int
main (int argc, char *argv[])
{
    PortableServer_POA poa;
    HiCorba_Hi servant = CORBA_OBJECT_NIL;
    CORBA_ORB orb=CORBA_OBJECT_NIL;
    CORBA_Environment ev;
 
    // init ORB
    g_print("\nServer>starting server...");
    g_print("\nServer>creating and initializing the ORB");
    CORBA_exception_init(&ev);
    abort_if_exception(&ev, "CORBA_exception_init failed");
    orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
    abort_if_exception(&ev, "CORBA_ORB_init failed");
 
    // activate POA
    g_print("\nServer>getting reference to RootPOA");
    poa= (PortableServer_POA) CORBA_ORB_resolve_initial_references(orb,"RootPOA",&ev);
    abort_if_exception(&ev, "CORBA_ORB_resolve_initial 'RootPOA' failed");
    g_print("\nServer>activating the POA Manager");
    PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, &ev),&ev);
    abort_if_exception(&ev, "POA_activate failed");
 
    // create servant
    g_print("\nServer>creating the servant");
    servant = impl_HiCorba_Hi__create (poa, &ev);
    abort_if_exception(&ev, "impl_HiCorba_Hi__create failed");
     
    // read name_service ior from ns.ior
    CORBA_char  filename[] = "service.ior";
    FILE *file   = NULL;
    g_print("\nServer>writing the file '%s'",filename);
    if ((file=fopen(filename, "w"))==NULL)
                g_error ("could not open '%s'\n", filename);
    gchar *objref = CORBA_ORB_object_to_string (orb, servant, &ev);
    abort_if_exception(&ev, "CORBA_ORB_object_to_string' failed");
        fprintf(file,"%s",objref);
        fflush(file);
        fclose(file);
    g_print("\nServer>writing the IOR to file '%s'",filename);
     
    // start
    g_print("\nServer>running the orb...");
    CORBA_ORB_run(orb,&ev);
    abort_if_exception(&ev, "ORB_run failed");
}

Hi-skelimpl.c

/* This is a template file generated by command */
/* orbit-idl-2 --skeleton-impl Hi.idl */
/* User must edit this file, inserting servant  */
/* specific code between markers. */
 
#include <stdlib.h>
#include <stdio.h>
#include "Hi.h"
 
/*** App-specific servant structures ***/
 
#if !defined(_typedef_impl_POA_HiCorba_Hi_)
#define _typedef_impl_POA_HiCorba_Hi_ 1
typedef struct {
POA_HiCorba_Hi servant;
PortableServer_POA poa;
   /* ------ add private attributes here ------ */
   /* ------ ---------- end ------------ ------ */
} impl_POA_HiCorba_Hi;
#endif
 
/*** Implementation stub prototypes ***/
 
#if !defined(_decl_impl_HiCorba_Hi__destroy_)
#define _decl_impl_HiCorba_Hi__destroy_ 1
static void impl_HiCorba_Hi__destroy(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_sayHiTo_)
#define _decl_impl_HiCorba_Hi_sayHiTo_ 1
static CORBA_string
impl_HiCorba_Hi_sayHiTo(impl_POA_HiCorba_Hi *servant,
const CORBA_char * someone,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_add_)
#define _decl_impl_HiCorba_Hi_add_ 1
static CORBA_long
impl_HiCorba_Hi_add(impl_POA_HiCorba_Hi *servant,
const CORBA_long numa,
const CORBA_long numb,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_shutdown_)
#define _decl_impl_HiCorba_Hi_shutdown_ 1
 
 
static void
impl_HiCorba_Hi_shutdown(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev);
#endif
 
 
/*** epv structures ***/
 
#if !defined(_impl_HiCorba_Hi_base_epv_)
#define _impl_HiCorba_Hi_base_epv_ 1
static PortableServer_ServantBase__epv impl_HiCorba_Hi_base_epv = {
NULL,             /* _private data */
(gpointer) & impl_HiCorba_Hi__destroy, /* finalize routine */
NULL,             /* default_POA routine */
};
#endif
 
#if !defined(_impl_HiCorba_Hi_epv_)
#define _impl_HiCorba_Hi_epv_ 1
static POA_HiCorba_Hi__epv impl_HiCorba_Hi_epv = {
NULL, /* _private */
(gpointer)&impl_HiCorba_Hi_sayHiTo,
(gpointer)&impl_HiCorba_Hi_add,
(gpointer)&impl_HiCorba_Hi_shutdown,
};
#endif
 
 
/*** vepv structures ***/
 
#if !defined(_impl_HiCorba_Hi_vepv_)
#define _impl_HiCorba_Hi_vepv_ 1
static POA_HiCorba_Hi__vepv impl_HiCorba_Hi_vepv = {
&impl_HiCorba_Hi_base_epv,
&impl_HiCorba_Hi_epv,
};
#endif
 
 
/*** Stub implementations ***/
 
#if !defined(_impl_HiCorba_Hi__create_)
#define _impl_HiCorba_Hi__create_ 1
static HiCorba_Hi impl_HiCorba_Hi__create(PortableServer_POA poa, CORBA_Environment *ev)
{
HiCorba_Hi retval;
impl_POA_HiCorba_Hi *newservant;
PortableServer_ObjectId *objid;
 
newservant = g_new0(impl_POA_HiCorba_Hi, 1);
newservant->servant.vepv = &impl_HiCorba_Hi_vepv;
newservant->poa = (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object)poa, ev);
POA_HiCorba_Hi__init((PortableServer_Servant)newservant, ev);
   /* Before servant is going to be activated all
    * private attributes must be initialized.  */
 
   /* ------ init private attributes here ------ */
   /* ------ ---------- end ------------- ------ */
 
objid = PortableServer_POA_activate_object(poa, newservant, ev);
CORBA_free(objid);
retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
 
return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi__destroy_)
#define _impl_HiCorba_Hi__destroy_ 1
static void
impl_HiCorba_Hi__destroy(impl_POA_HiCorba_Hi *servant, CORBA_Environment *ev)
{
    CORBA_Object_release ((CORBA_Object) servant->poa, ev);
 
    /* No further remote method calls are delegated to
    * servant and you may free your private attributes. */
   /* ------ free private attributes here ------ */
   /* ------ ---------- end ------------- ------ */
 
POA_HiCorba_Hi__fini((PortableServer_Servant)servant, ev);
 
g_free (servant);
}
#endif
 
#if !defined(_impl_HiCorba_Hi_sayHiTo_)
#define _impl_HiCorba_Hi_sayHiTo_ 1
static CORBA_string
impl_HiCorba_Hi_sayHiTo(impl_POA_HiCorba_Hi *servant,
const CORBA_char * someone,
CORBA_Environment *ev)
{
 CORBA_string retval = CORBA_string_alloc(512);
 /* ------   insert method code here   ------ */
 sprintf(retval,"Hi, %s !",someone);
 g_print("\nServer>server is returning: %s",retval);
 
 /* ------ ---------- end ------------ ------ */
 
 return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi_add_)
#define _impl_HiCorba_Hi_add_ 1
static CORBA_long
impl_HiCorba_Hi_add(impl_POA_HiCorba_Hi *servant,
const CORBA_long numa,
const CORBA_long numb,
CORBA_Environment *ev)
{
 CORBA_long retval;
 /* ------   insert method code here   ------ */
 retval = numa+numb;
 /* ------ ---------- end ------------ ------ */
 
 return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi_shutdown_)
#define _impl_HiCorba_Hi_shutdown_ 1
static CORBA_ORB _neo_ORB = CORBA_OBJECT_NIL;
static HiCorba_Hi _neo_servant =  CORBA_OBJECT_NIL;
static void set_NEO_ORB(CORBA_ORB theORB, HiCorba_Hi theServant)
{
    _neo_ORB = theORB;
    _neo_servant = theServant;
}
 
static void
impl_HiCorba_Hi_shutdown(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev)
{
 /* ------   insert method code here   ------ */
 if(_neo_ORB==CORBA_OBJECT_NIL || _neo_servant ==  CORBA_OBJECT_NIL)return;
 //
 g_print("\nServer>executing the release");
 CORBA_Object_release(_neo_servant,ev);
 if((ev)->_major != CORBA_NO_EXCEPTION){
   g_error ("%s %s", "Object_release failed", CORBA_exception_id (ev));
   CORBA_exception_free (ev);
   abort();
 }
 //
 g_print("\nServer>executing the shutdown");
 CORBA_ORB_shutdown(_neo_ORB, CORBA_FALSE, ev);
 if((ev)->_major != CORBA_NO_EXCEPTION){
   g_error ("%s %s", "shutdown failed", CORBA_exception_id (ev));
   CORBA_exception_free (ev);
   abort();
 }
 exit(0);
 /* ------ ---------- end ------------ ------ */
}
#endif

MakeServer

CC       = gcc
CFLAGS   = -c -g -pthread -D_REENTRANT -DORBIT2=1 \
           -I/usr/include/orbit-2.0 \
           -I/usr/include/glib-2.0 \
           -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDFLAGS  = -Wl,--export-dynamic -lORBit-2 -lORBitCosNaming-2 -lgmodule-2.0 \
           -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm \
           -L/usr/lib
ORBIT_IDL= /usr/bin/orbit-idl-2
 
all : Hi-server-ior.bin
 
Hi-server-ior.bin : Hi-common.o Hi-skelimpl.o Hi-skels.o Hi-server-ior.o
    $(CC) $(LDFLAGS) Hi-common.o Hi-skelimpl.o Hi-skels.o Hi-server-ior.o -o Hi-server-ior.bin
 
%.o : %.c
    $(CC) $(CFLAGS) $< -o $@
 
nidl : Hi.idl
    $(ORBIT_IDL) Hi.idl
    $(ORBIT_IDL) --skeleton-impl Hi.idl
 
clean:
    rm -rf *.bin
    rm -rf *.o

编译

make -f MakeServer

CPP实现CORBA静态绑定(六)

  • CORBA基本架构
  • IDL文件编写
  • CPP示例实现(上)
  • CPP示例实现(下)
  • C示例实现(IOR+NS上)
  • C示例实现(IOR+NS下)
  • C示例实现(IOR上)
  • C示例实现(IOR下)

首先完成客户端部分:
Hi-client-ns.c

#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <orbit/orbit.h>
#include <ORBitservices/CosNaming.h>
#include <ORBitservices/CosNaming_impl.h>
 
#include "Hi.h"
 
/*
Usage: ./hi-client_ns
*/
 
/**
 * test for exception
 */
static
gboolean
raised_exception(CORBA_Environment *ev)
{
    return ((ev)->_major != CORBA_NO_EXCEPTION);
}
 
/**
 * in case of any exception this macro will abort the process
 */
static
void
abort_if_exception(CORBA_Environment *ev, const char* mesg)
{
    if (raised_exception (ev)) {
        g_error ("%s %s", mesg, CORBA_exception_id (ev));
        CORBA_exception_free (ev);
        abort();
    }
}
 
 
/*
 * main
 */
int main(int argc, char* argv[])
{
    CORBA_ORB orb=CORBA_OBJECT_NIL;
    CORBA_Environment ev;
    CosNaming_NamingContext ns =CORBA_OBJECT_NIL;
    HiCorba_Hi service = CORBA_OBJECT_NIL;
    CORBA_char  name_service[]="Hi";
    CosNaming_NameComponent path[1]={name_service,""};
    CosNaming_Name name={1,1,path,CORBA_FALSE};
 
    //init orb
    g_print("\nClient>starting client...");
    g_print("\nClient>creating and initializing the ORB");
    CORBA_exception_init(&ev);
    abort_if_exception(&ev, "CORBA_exception_init failed");
    orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
    abort_if_exception(&ev, "CORBA_ORB_init failed");
 
    // read name_service ior from ns.ior
    CORBA_char  filename[] = "ns.ior";
    FILE *file   = NULL;
    g_print("\nClient>reading the file '%s'",filename);
    if ((file=fopen(filename, "r"))==NULL)
                g_error ("could not open '%s'", filename);
    gchar objref[1024];
    fscanf (file, "%s", &objref);
    g_print("\nClient>getting the root naming context 'NameService' - from the file '%s'",filename);
    g_print("\nClient>the root naming context ior is '%s'",objref);
        ns = (CosNaming_NamingContext)CORBA_ORB_string_to_object(orb,objref,&ev);
    //free (objref);
    abort_if_exception(&ev, "CORBA_ORB_string_to_object 'NameService IOR' failed");
 
        //resolve object reference
    g_print("\nClient>Resolving the object reference in naming '%s'",name_service);
    service=CosNaming_NamingContext_resolve(ns,&name,&ev);
    abort_if_exception(&ev, "resolve failed");
 
    // invoke service
    g_print("\nClient>calling the Hi service...");
    CORBA_char *msg=HiCorba_Hi_sayHiTo(service, "neohope", &ev);
    abort_if_exception(&ev, "HiCorba_Hi_sayHiTo failed");
        g_print("\nClient>server returned the following message: %s\n", msg);
 
    CORBA_Object_release(service, &ev);
    abort_if_exception(&ev, "release failed");
 
        if (orb != CORBA_OBJECT_NIL)
        {
           /* going to destroy orb.. */
           CORBA_ORB_destroy(orb, &ev);
       abort_if_exception(&ev, "destroy failed");
    }
 
}

MakeClient

CC       = gcc
CFLAGS   = -c -g -pthread -D_REENTRANT -DORBIT2=1 \
           -I/usr/include/orbit-2.0 \
           -I/usr/include/glib-2.0 \
           -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDFLAGS  = -Wl,--export-dynamic -lORBit-2 -lORBitCosNaming-2 -lgmodule-2.0 \
           -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm \
           -L/usr/lib
ORBIT_IDL= /usr/bin/orbit-idl-2
 
all : Hi-client-ns.bin
 
Hi-client-ns.bin : Hi-common.o Hi-stubs.o Hi-client-ns.o
    $(CC) $(LDFLAGS) Hi-common.o Hi-stubs.o Hi-client-ns.o -o Hi-client-ns.bin
 
%.o : %.c
    $(CC) $(CFLAGS) $< -o $@
 
nidl : Hi.idl
    $(ORBIT_IDL) Hi.idl
    $(ORBIT_IDL) --skeleton-impl Hi.idl
 
clean:
    rm -rf *.bin
    rm -rf *.o

编译

make -f MakeClient

然后是运行

#首先运行orbd
orbd -ORBInitialPort 1900
 
#然后运行nameservice
orbit-name-server-2 > ns.ior
 
#然后运行server
./Hi-server-ns.bin
Server>starting server...
Server>creating and initializing the ORB
Server>getting reference to RootPOA
Server>activating the POA Manager
Server>creating the servant
Server>reading the file 'ns.ior'
Server>getting the root naming context 'NameService' - from the file 'ns.ior'
Server>the root naming context ior is 'IOR:010000002b00000049444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578744578743a312e300000030000000054424f580000000101020005000000554e4958000000000a0000006c6f63616c686f73740000002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d313735302d302d346431323731616531616661390000000000000000caaedfba58000000010102002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d313735302d302d34643132373161653161666139000000001c00000000000000d4d2dcc0a89f68a8c02b28282828282801000000eaaf213d01000000480000000100000002000000050000001c00000000000000d4d2dcc0a89f68a8c02b28282828282801000000eaaf213d01000000140000000100000001000105000000000901010000000000'
Server>binding the object reference in naming with name 'Hi'
Server>running the orb...
Server>server is returning: Hi, neohope !
 
#然后运行client
./Hi-client-ns.bin
Client>starting client...
Client>creating and initializing the ORB
Client>reading the file 'ns.ior'
Client>getting the root naming context 'NameService' - from the file 'ns.ior'
Client>the root naming context ior is 'IOR:010000002b00000049444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578744578743a312e300000030000000054424f580000000101020005000000554e4958000000000a0000006c6f63616c686f73740000002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d313735302d302d346431323731616531616661390000000000000000caaedfba58000000010102002d0000002f746d702f6f726269742d6e656f686f70652f6c696e632d313735302d302d34643132373161653161666139000000001c00000000000000d4d2dcc0a89f68a8c02b28282828282801000000eaaf213d01000000480000000100000002000000050000001c00000000000000d4d2dcc0a89f68a8c02b28282828282801000000eaaf213d01000000140000000100000001000105000000000901010000000000'
Client>Resolving the object reference in naming 'Hi'
Client>calling the Hi service...
Client>server returned the following message: Hi, neohope !

CPP实现CORBA静态绑定(五)

  • CORBA基本架构
  • IDL文件编写
  • CPP示例实现(上)
  • CPP示例实现(下)
  • C示例实现(IOR+NS上)
  • C示例实现(IOR+NS下)
  • C示例实现(IOR上)
  • C示例实现(IOR下)

在linux系统下,有很多开源的CORBA通讯框架,在C的示例中,使用了orbit的框架。
如我用的是Debian系统,可以直接安装:

apt-get install orbit2
apt-get install orbit2-nameserver
apt-get install liborbit2-dev

安装后,可以通过工具orb-rdl-2从idl文件生成需要的stubs及skeletons接口代码:

#该命令会生成文件:Hi.h、Hi-common.c、Hi-skels.c、Hi-stubs.c
orbit-idl-2 Hi.idl

可以通过工具orb-rdl-2从idl文件生成服务端代码:

#该命令会生成模板文件:Hi-skelimpl.c
orbit-idl-2 --skeleton-impl Hi.idl

首先完成服务端部分:
Hi-server-ns.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>
#include <ORBitservices/CosNaming.h>
#include <ORBitservices/CosNaming_impl.h>
#include "Hi.h"
#include "Hi-skelimpl.c"
/*
./Hi-server_ns
*/
 
/**
 * test for exception
*/
static
gboolean
raised_exception(CORBA_Environment *ev) {
    return ((ev)->_major != CORBA_NO_EXCEPTION);
}
 
/**
 * in case of any exception this macro will abort the process
*/
static
void
abort_if_exception(CORBA_Environment *ev, const char* mesg)
{
    if (raised_exception (ev)) {
        g_error ("%s %s", mesg, CORBA_exception_id (ev));
        CORBA_exception_free (ev);
        abort();
    }
}
 
/*
 * main
*/
int
main (int argc, char *argv[])
{
    PortableServer_POA poa;
    HiCorba_Hi servant = CORBA_OBJECT_NIL;
    CosNaming_NamingContext ns =CORBA_OBJECT_NIL;
    CORBA_ORB orb=CORBA_OBJECT_NIL;
    CORBA_char name_service[]="Hi";
    CosNaming_NameComponent path[1]={name_service,""};
    CosNaming_Name name={1,1,path,CORBA_FALSE};
    CORBA_Environment ev;
 
    // init ORB
    g_print("\nServer>starting server...");
    g_print("\nServer>creating and initializing the ORB");
    CORBA_exception_init(&ev);
    abort_if_exception(&ev, "CORBA_exception_init failed");
    orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
    abort_if_exception(&ev, "CORBA_ORB_init failed");
 
    // activate POA
    g_print("\nServer>getting reference to RootPOA");
    poa= (PortableServer_POA) CORBA_ORB_resolve_initial_references(orb,"RootPOA",&ev);
    abort_if_exception(&ev, "CORBA_ORB_resolve_initial 'RootPOA' failed");
    g_print("\nServer>activating the POA Manager");
    PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, &ev),&ev);
    abort_if_exception(&ev, "POA_activate failed");
 
    // create servant
    g_print("\nServer>creating the servant");
    servant = impl_HiCorba_Hi__create (poa, &ev);
    abort_if_exception(&ev, "impl_HiCorba_Hi__create failed");
     
    // read name_service ior from ns.ior
    CORBA_char  filename[] = "ns.ior";
    FILE *file   = NULL;
    g_print("\nServer>reading the file '%s'",filename);
    if ((file=fopen(filename, "r"))==NULL)
                g_error ("could not open '%s'\n", filename);
    gchar objref[1024];
    fscanf (file, "%s", &objref);
    g_print("\nServer>getting the root naming context 'NameService' - from the file '%s'",filename);
    g_print("\nServer>the root naming context ior is '%s'",objref);
 
    // bind service
    ns = (CosNaming_NamingContext) CORBA_ORB_string_to_object (orb, objref, &ev);
    //free (objref);
    abort_if_exception(&ev, "CORBA_ORB_string_to_object 'NameService IOR' failed");
    g_print("\nServer>binding the object reference in naming with name '%s'",name_service);
    CosNaming_NamingContext_rebind(ns,&name,servant,&ev);
    abort_if_exception(&ev, "rebind failed");
     
    // start
    g_print("\nServer>running the orb...");
    CORBA_ORB_run(orb,&ev);
    abort_if_exception(&ev, "ORB_run failed");
}

Hi-skelimpl.c

/* This is a template file generated by command */
/* orbit-idl-2 --skeleton-impl Hi.idl */
/* User must edit this file, inserting servant  */
/* specific code between markers. */
 
#include <stdlib.h>
#include <stdio.h>
#include "Hi.h"
 
/*** App-specific servant structures ***/
 
#if !defined(_typedef_impl_POA_HiCorba_Hi_)
#define _typedef_impl_POA_HiCorba_Hi_ 1
typedef struct {
POA_HiCorba_Hi servant;
PortableServer_POA poa;
   /* ------ add private attributes here ------ */
   /* ------ ---------- end ------------ ------ */
} impl_POA_HiCorba_Hi;
#endif
 
/*** Implementation stub prototypes ***/
 
#if !defined(_decl_impl_HiCorba_Hi__destroy_)
#define _decl_impl_HiCorba_Hi__destroy_ 1
static void impl_HiCorba_Hi__destroy(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_sayHiTo_)
#define _decl_impl_HiCorba_Hi_sayHiTo_ 1
static CORBA_string
impl_HiCorba_Hi_sayHiTo(impl_POA_HiCorba_Hi *servant,
const CORBA_char * someone,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_add_)
#define _decl_impl_HiCorba_Hi_add_ 1
static CORBA_long
impl_HiCorba_Hi_add(impl_POA_HiCorba_Hi *servant,
const CORBA_long numa,
const CORBA_long numb,
CORBA_Environment *ev);
#endif
 
#if !defined(_decl_impl_HiCorba_Hi_shutdown_)
#define _decl_impl_HiCorba_Hi_shutdown_ 1
 
 
static void
impl_HiCorba_Hi_shutdown(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev);
#endif
 
 
/*** epv structures ***/
 
#if !defined(_impl_HiCorba_Hi_base_epv_)
#define _impl_HiCorba_Hi_base_epv_ 1
static PortableServer_ServantBase__epv impl_HiCorba_Hi_base_epv = {
NULL,             /* _private data */
(gpointer) & impl_HiCorba_Hi__destroy, /* finalize routine */
NULL,             /* default_POA routine */
};
#endif
 
#if !defined(_impl_HiCorba_Hi_epv_)
#define _impl_HiCorba_Hi_epv_ 1
static POA_HiCorba_Hi__epv impl_HiCorba_Hi_epv = {
NULL, /* _private */
(gpointer)&impl_HiCorba_Hi_sayHiTo,
(gpointer)&impl_HiCorba_Hi_add,
(gpointer)&impl_HiCorba_Hi_shutdown,
};
#endif
 
 
/*** vepv structures ***/
 
#if !defined(_impl_HiCorba_Hi_vepv_)
#define _impl_HiCorba_Hi_vepv_ 1
static POA_HiCorba_Hi__vepv impl_HiCorba_Hi_vepv = {
&impl_HiCorba_Hi_base_epv,
&impl_HiCorba_Hi_epv,
};
#endif
 
 
/*** Stub implementations ***/
 
#if !defined(_impl_HiCorba_Hi__create_)
#define _impl_HiCorba_Hi__create_ 1
static HiCorba_Hi impl_HiCorba_Hi__create(PortableServer_POA poa, CORBA_Environment *ev)
{
HiCorba_Hi retval;
impl_POA_HiCorba_Hi *newservant;
PortableServer_ObjectId *objid;
 
newservant = g_new0(impl_POA_HiCorba_Hi, 1);
newservant->servant.vepv = &impl_HiCorba_Hi_vepv;
newservant->poa = (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object)poa, ev);
POA_HiCorba_Hi__init((PortableServer_Servant)newservant, ev);
   /* Before servant is going to be activated all
    * private attributes must be initialized.  */
 
   /* ------ init private attributes here ------ */
   /* ------ ---------- end ------------- ------ */
 
objid = PortableServer_POA_activate_object(poa, newservant, ev);
CORBA_free(objid);
retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
 
return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi__destroy_)
#define _impl_HiCorba_Hi__destroy_ 1
static void
impl_HiCorba_Hi__destroy(impl_POA_HiCorba_Hi *servant, CORBA_Environment *ev)
{
    CORBA_Object_release ((CORBA_Object) servant->poa, ev);
 
    /* No further remote method calls are delegated to
    * servant and you may free your private attributes. */
   /* ------ free private attributes here ------ */
   /* ------ ---------- end ------------- ------ */
 
POA_HiCorba_Hi__fini((PortableServer_Servant)servant, ev);
 
g_free (servant);
}
#endif
 
#if !defined(_impl_HiCorba_Hi_sayHiTo_)
#define _impl_HiCorba_Hi_sayHiTo_ 1
static CORBA_string
impl_HiCorba_Hi_sayHiTo(impl_POA_HiCorba_Hi *servant,
const CORBA_char * someone,
CORBA_Environment *ev)
{
 CORBA_string retval = CORBA_string_alloc(512);
 /* ------   insert method code here   ------ */
 sprintf(retval,"Hi, %s !",someone);
 g_print("\nServer>server is returning: %s",retval);
 
 /* ------ ---------- end ------------ ------ */
 
 return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi_add_)
#define _impl_HiCorba_Hi_add_ 1
static CORBA_long
impl_HiCorba_Hi_add(impl_POA_HiCorba_Hi *servant,
const CORBA_long numa,
const CORBA_long numb,
CORBA_Environment *ev)
{
 CORBA_long retval;
 /* ------   insert method code here   ------ */
 retval = numa+numb;
 /* ------ ---------- end ------------ ------ */
 
 return retval;
}
#endif
 
#if !defined(_impl_HiCorba_Hi_shutdown_)
#define _impl_HiCorba_Hi_shutdown_ 1
static CORBA_ORB _neo_ORB = CORBA_OBJECT_NIL;
static HiCorba_Hi _neo_servant =  CORBA_OBJECT_NIL;
static void set_NEO_ORB(CORBA_ORB theORB, HiCorba_Hi theServant)
{
    _neo_ORB = theORB;
    _neo_servant = theServant;
}
 
static void
impl_HiCorba_Hi_shutdown(impl_POA_HiCorba_Hi *servant,
CORBA_Environment *ev)
{
 /* ------   insert method code here   ------ */
 if(_neo_ORB==CORBA_OBJECT_NIL || _neo_servant ==  CORBA_OBJECT_NIL)return;
 //
 g_print("\nServer>executing the release");
 CORBA_Object_release(_neo_servant,ev);
 if((ev)->_major != CORBA_NO_EXCEPTION){
   g_error ("%s %s", "Object_release failed", CORBA_exception_id (ev));
   CORBA_exception_free (ev);
   abort();
 }
 //
 g_print("\nServer>executing the shutdown");
 CORBA_ORB_shutdown(_neo_ORB, CORBA_FALSE, ev);
 if((ev)->_major != CORBA_NO_EXCEPTION){
   g_error ("%s %s", "shutdown failed", CORBA_exception_id (ev));
   CORBA_exception_free (ev);
   abort();
 }
 exit(0);
 /* ------ ---------- end ------------ ------ */
}
#endif

MakeServer

CC       = gcc
CFLAGS   = -c -g -pthread -D_REENTRANT -DORBIT2=1 \
           -I/usr/include/orbit-2.0 \
           -I/usr/include/glib-2.0 \
           -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDFLAGS  = -Wl,--export-dynamic -lORBit-2 -lORBitCosNaming-2 -lgmodule-2.0 \
           -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm \
           -L/usr/lib
ORBIT_IDL= /usr/bin/orbit-idl-2
 
all : Hi-server-ns.bin
 
Hi-server-ns.bin : Hi-common.o Hi-skelimpl.o Hi-skels.o Hi-server-ns.o
    $(CC) $(LDFLAGS) Hi-common.o Hi-skelimpl.o Hi-skels.o Hi-server-ns.o -o Hi-server-ns.bin
 
%.o : %.c
    $(CC) $(CFLAGS) $< -o $@
 
nidl : Hi.idl
    $(ORBIT_IDL) Hi.idl
    $(ORBIT_IDL) --skeleton-impl Hi.idl
 
clean:
    rm -rf *.bin
    rm -rf *.o

编译

make -f MakeServer

DBUS发送接收数据(下)

1、编译后,由于没有进行配置,默认是无法运行的。
为了可以正常运行,增加或修改下面的配置文件即可。
/etc/dbus-1.0/system-local.conf

<!-- This configuration file controls the systemwide message bus.
     Add a system-local.conf and edit that rather than changing this
     file directly. -->
 
<!-- Note that there are any number of ways you can hose yourself
     security-wise by screwing up this file; in particular, you
     probably don't want to listen on any more addresses, add any more
     auth mechanisms, run as a different user, etc. -->
 
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
 
  <!-- Our well-known bus type, do not change this -->
  <type>system</type>
 
  <!-- Run as special user -->
  <user>messagebus</user>
 
  <!-- Fork into daemon mode -->
  <fork/>
 
  <!-- We use system service launching using a helper -->
  <standard_system_servicedirs/>
 
  <!-- This is a setuid helper that is used to launch system services -->
  <servicehelper>/usr/lib/dbus-1.0/dbus-daemon-launch-helper</servicehelper>
 
  <!-- Write a pid file -->
  <pidfile>/var/run/dbus/pid</pidfile>
 
  <!-- Enable logging to syslog -->
  <syslog/>
 
  <!-- Only allow socket-credentials-based authentication -->
  <auth>EXTERNAL</auth>
 
  <!-- Only listen on a local socket. (abstract=/path/to/socket
       means use abstract namespace, don't really create filesystem
       file; only Linux supports this. Use path=/whatever on other
       systems.) -->
  <listen>unix:path=/var/run/dbus/system_bus_socket</listen>
 
  <policy context="default">
    <!-- All users can connect to system bus -->
    <allow user="*"/>
 
    <!-- Holes must be punched in service configuration files for
         name ownership and sending method calls -->
    <allow own="*"/>
    <allow send_type="method_call"/>
 
    <!-- Signals and reply messages (method returns, errors) are allowed
         by default -->
    <allow send_type="signal"/>
    <allow send_requested_reply="true" send_type="method_return"/>
    <allow send_requested_reply="true" send_type="error"/>
 
    <!-- All messages may be received by default -->
    <allow receive_type="method_call"/>
    <allow receive_type="method_return"/>
    <allow receive_type="error"/>
    <allow receive_type="signal"/>
 
    <!-- Allow anyone to talk to the message bus -->
    <allow send_destination="org.freedesktop.DBus"/>
    <!-- But disallow some specific bus services -->
    <deny send_destination="org.freedesktop.DBus"
          send_interface="org.freedesktop.DBus"
          send_member="UpdateActivationEnvironment"/>
    <deny send_destination="org.freedesktop.DBus"
          send_interface="org.freedesktop.systemd1.Activator"/>
  </policy>
 
  <!-- Only systemd, which runs as root, may report activation failures. -->
  <policy user="root">
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.systemd1.Activator"/>
  </policy>
 
  <!-- Config files are placed here that among other things, punch
       holes in the above policy for specific services. -->
  <includedir>system.d</includedir>
 
  <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
 
</busconfig>

2、测试消息发送
服务端:

$./testdbus_s.bin receive
Listening for signals
Match rule sent
Got Signal with value: Hello
Got Signal with value: Hi
Bye......

客户端:

$./testdbus_s.bin send Hello
Sending signal with value: Hello
Signal Sent
 
$./testdbus_s.bin send Hi
Sending signal with value: Hi
Signal Sent
 
$./testdbus_s.bin send Bye
Sending signal with value: Bye
Signal Sent

3、测试方法调用
服务端:

$./testdbus_s.bin listen
Listening for method calls
Method Invoked with value: Hello
Method Invoked with value: Hi
Bye......

客户端:

$./testdbus_s.bin query Hello
Calling remote method with Hello
Request Sent
Got Reply: 1, 21614
 
$./testdbus_s.bin query Hi
Calling remote method with Hi
Request Sent
Got Reply: 1, 21614
 
$./testdbus_s.bin query Bye
Calling remote method with Bye
Request Sent
Got Reply: 1, 21614

DBUS发送接收数据(上)

1、Server端
testdbus_s.c

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
/**
 * Wait for signals on the bus and reply
 */
void receive()
{
  DBusMessage* msg;
  DBusMessageIter args;
  DBusConnection* conn;
  DBusError err;
  int ret;
  char* sigvalue;
  int loop=1;
 
  printf("Listening for signals\n");
 
  // initialise the errors
  dbus_error_init(&err);
   
  // connect to the bus and check for errors
  conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Connection Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (NULL == conn) {
     exit(1);
  }
   
  // request our name on the bus and check for errors
  ret = dbus_bus_request_name(conn, "neohope.dbus.signal.target", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Name Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
     exit(1);
  }
 
  // add a rule for which messages we want to see
  dbus_bus_add_match(conn, "type='signal',interface='neohope.dbus.signal.Type'", &err); // see signals from the given interface
  dbus_connection_flush(conn);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Match Error (%s)\n", err.message);
     exit(1);
  }
  printf("Match rule sent\n");
 
  // loop listening for signals being emmitted
  while (loop) {
 
     // non blocking read of the next available message
     dbus_connection_read_write(conn, 0);
     msg = dbus_connection_pop_message(conn);
 
     // loop again if we haven't read a message
     if (NULL == msg) {
        sleep(1);
        continue;
     }
 
     // check if the message is a signal from the correct interface and with the correct name
     if (dbus_message_is_signal(msg, "neohope.dbus.signal.Type", "TestSignal")) {
         
        // read the parameters
        if (!dbus_message_iter_init(msg, &args))
           fprintf(stderr, "Message Has No Parameters\n");
        else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
           fprintf(stderr, "Argument is not string!\n");
        else
           dbus_message_iter_get_basic(&args, &sigvalue);
         
        if(strcmp("Bye",sigvalue)==0) {
           loop = 0;
           printf("Bye......\n");
        }
        else {
          printf("Got Signal with value: %s\n", sigvalue);
        }
     }
 
     // free the message
     dbus_message_unref(msg);
  }
  // do not close the connection
  // dbus_connection_close(conn);
}
 
/**
 * Deal with remote method call
 */
int reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
{
  DBusMessage* reply;
  DBusMessageIter args;
  int stat = 1;
  int ret = 1;
  dbus_uint32_t level = 21614;
  dbus_uint32_t serial = 0;
  char* param = "";
 
  // read the arguments
  if (!dbus_message_iter_init(msg, &args))
     fprintf(stderr, "Message has no arguments!\n");
  else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
     fprintf(stderr, "Argument is not string!\n");
  else
     dbus_message_iter_get_basic(&args, &param);
 
  if(strcmp("Bye",param)==0){
    ret = 0;
    printf ("Bye......\n");
  }
  else {
    printf("Method Invoked with value: %s\n", sigvalue);
  }
 
  // create a reply from the message
  reply = dbus_message_new_method_return(msg);
 
  // add the arguments to the reply
  dbus_message_iter_init_append(reply, &args);
  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
 
  // send the reply && flush the connection
  if (!dbus_connection_send(conn, reply, &serial)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
  dbus_connection_flush(conn);
 
  // free the reply
  dbus_message_unref(reply);
   
  return ret;
}
 
/**
 * Server that exposes a method call and waits for it to be called
 */
void listen()
{
  DBusMessage* msg;
  DBusMessage* reply;
  DBusMessageIter args;
  DBusConnection* conn;
  DBusError err;
  int loop = 1;
  int ret;
  char* param;
 
  printf("Listening for method calls\n");
 
  // initialise the error
  dbus_error_init(&err);
   
  // connect to the bus and check for errors
  conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Connection Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (NULL == conn) {
     fprintf(stderr, "Connection Null\n");
     exit(1);
  }
   
  // request our name on the bus and check for errors
  ret = dbus_bus_request_name(conn, "neohope.dbus.method.provider", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Name Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
     fprintf(stderr, "Not Primary Owner (%d)\n", ret);
     exit(1);
  }
 
  // loop, testing for new messages
  while (loop) {
     // non blocking read of the next available message
     dbus_connection_read_write(conn, 0);
     msg = dbus_connection_pop_message(conn);
 
     // loop again if we haven't got a message
     if (NULL == msg) {
        sleep(1);
        continue;
     }
      
     // check this is a method call for the right interface & method
     if (dbus_message_is_method_call(msg, "neohope.dbus.method.Type", "TestMethod"))
        loop = reply_to_method_call(msg, conn);
 
     // free the message
     dbus_message_unref(msg);
  }
 
  // do not close the connection
  // dbus_connection_close(conn);
}
 
int main(int argc, char** argv)
{
  if (2 > argc) {
     printf ("Syntax: testdbus_s [receive|listen] [<param>]\n");
     return 1;
  }
  char* param = "no param";
  if (3 >= argc && NULL != argv[2]) param = argv[2];
 
  if (0 == strcmp(argv[1], "receive"))
     receive();
  else if (0 == strcmp(argv[1], "listen"))
     listen();
  else {
     printf ("Syntax: testdbus_s [receive|listen] [<param>]\n");
     return 1;
  }
  return 0;
}

2、Client端
testdbus_c.c

#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
/**
 * Connect to the DBUS bus and send a broadcast signal
 */
void sendsignal(char* sigvalue)
{
  DBusMessage* msg;
  DBusMessageIter args;
  DBusConnection* conn;
  DBusError err;
  int ret;
  dbus_uint32_t serial = 0;
 
  printf("Sending signal with value: %s\n", sigvalue);
 
  // initialise the error value
  dbus_error_init(&err);
 
  // connect to the DBUS system bus, and check for errors
  conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Connection Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (NULL == conn) {
     exit(1);
  }
 
  // register our name on the bus, and check for errors
  ret = dbus_bus_request_name(conn, "neohope.dbus.signal.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Name Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
     exit(1);
  }
 
  // create a signal & check for errors
  msg = dbus_message_new_signal("/neohope/dbus/signal/Object", // object name of the signal
                                "neohope.dbus.signal.Type", // interface name of the signal
                                "TestSignal"); // name of the signal
  if (NULL == msg)
  {
     fprintf(stderr, "Message Null\n");
     exit(1);
  }
 
  // append arguments onto signal
  dbus_message_iter_init_append(msg, &args);
  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
 
  // send the message and flush the connection
  if (!dbus_connection_send(conn, msg, &serial)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
  dbus_connection_flush(conn);
   
  printf("Signal Sent\n");
   
  // free the message
  dbus_message_unref(msg);
  // do not close the connection
  // dbus_connection_close(conn);
}
 
/**
 * Call a method on a remote object
 */
void query(char* param)
{
  DBusMessage* msg;
  DBusMessageIter args;
  DBusConnection* conn;
  DBusError err;
  DBusPendingCall* pending;
  int ret;
  int stat;
  dbus_uint32_t level;
 
  printf("Calling remote method with %s\n", param);
 
  // initialiset the errors
  dbus_error_init(&err);
 
  // connect to the system bus and check for errors
  conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Connection Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (NULL == conn) {
     exit(1);
  }
 
  // request our name on the bus
  ret = dbus_bus_request_name(conn, "neohope.dbus.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
  if (dbus_error_is_set(&err)) {
     fprintf(stderr, "Name Error (%s)\n", err.message);
     dbus_error_free(&err);
  }
  if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
     exit(1);
  }
 
  // create a new method call and check for errors
  msg = dbus_message_new_method_call("neohope.dbus.method.provider", // target for the method call
                                     "/neohope/dbus/method/Object", // object to call on
                                     "neohope.dbus.method.Type", // interface to call on
                                     "TestMethod"); // method name
  if (NULL == msg) {
     fprintf(stderr, "Message Null\n");
     exit(1);
  }
 
  // append arguments
  dbus_message_iter_init_append(msg, &args);
  if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &param)) {
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
   
  // send message and get a handle for a reply
  if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout
     fprintf(stderr, "Out Of Memory!\n");
     exit(1);
  }
  if (NULL == pending) {
     fprintf(stderr, "Pending Call Null\n");
     exit(1);
  }
  dbus_connection_flush(conn);
   
  printf("Request Sent\n");
   
  // free message
  dbus_message_unref(msg);
   
  // block until we recieve a reply
  dbus_pending_call_block(pending);
 
  // get the reply message
  msg = dbus_pending_call_steal_reply(pending);
  if (NULL == msg) {
     fprintf(stderr, "Reply Null\n");
     exit(1);
  }
  // free the pending message handle
  dbus_pending_call_unref(pending);
 
  // read the parameters
  if (!dbus_message_iter_init(msg, &args))
     fprintf(stderr, "Message has no arguments!\n");
  else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))
     fprintf(stderr, "Argument is not boolean!\n");
  else
     dbus_message_iter_get_basic(&args, &stat);
 
  if (!dbus_message_iter_next(&args))
     fprintf(stderr, "Message has too few arguments!\n");
  else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
     fprintf(stderr, "Argument is not int!\n");
  else
     dbus_message_iter_get_basic(&args, &level);
 
  printf("Got Reply: %d, %d\n", stat, level);
   
  // free reply and close connection
  dbus_message_unref(msg);  
  //dbus_connection_close(conn);
}
 
int main(int argc, char** argv)
{
  if (2 > argc) {
     printf ("Syntax: testdbus_c [send|query] [<param>]\n");
     return 1;
  }
  char* param = "no param";
  if (3 >= argc && NULL != argv[2]) param = argv[2];
 
  if (0 == strcmp(argv[1], "send"))
     sendsignal(param);
  else if (0 == strcmp(argv[1], "query"))
     query(param);
  else {
     printf ("Syntax: testdbus_c [send|query] [<param>]\n");
     return 1;
  }
  return 0;
}

3、Makefile

CC=gcc
LDFLAGS+=-ldbus-1
CFLAGS+=-I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/
 
all:testdbus_c.bin testdbus_s.bin
 
testdbus_c.bin:testdbus_c.o
    $(CC) $(LDFLAGS) -o testdbus_c.bin testdbus_c.o
 
testdbus_c.o:testdbus_c.c
    $(CC) $(CFLAGS) -c -o testdbus_c.o testdbus_c.c
 
testdbus_s.bin:testdbus_s.o
    $(CC) $(LDFLAGS) -o testdbus_s.bin testdbus_s.o
 
testdbus_s.o:testdbus_s.c
    $(CC) $(CFLAGS) -c -o testdbus_s.o testdbus_s.c
 
clean:
    rm *.o *.bin

4、编译

make

排序算法C Part01

1、冒泡排序

//冒泡排序BubbleSort
//每次扫描,比较和交换相邻元素,保证一次扫描后,最大元素在最后一个
//每次扫描后,扫描队列长度减一
//时间复杂度:O(N^2)
//空间复杂度:O(N)
//稳定性:稳定
//输入:要排序的数组,数组长度
//输出:void,Q[]将处于排序状态
void BubbleSort(int Q[], int N)
{
  int i;
  int swap=1;
  int Temp;
   
  while(swap>0)
    {
      swap=0;
      for(i=1;i<N;i++)
    {
      if(Q[i-1]>Q[i])
        {
          swap++;
          Temp=Q[i-1];
          Q[i-1]=Q[i];
          Q[i]=Temp;
        }
    }
    }
}

2、选择排序

//选择排序SelectionSort
//从头扫描到尾,每次将最小元素放到第一个
//每次扫描后,队列长度减一
//时间复杂度:O(N^2)
//空间复杂度:O(N)
//稳定性:稳定
//输入:要排序的数组,数组长度
//输出:void,Q[]将处于排序状态
void SelectionSort(int Q[], int N)
{
  int i,j,k;
  int Temp;
  for(i=0;i<N;i++)
    {
      k=i;
      for(j=i+1;j<N;j++)
    {
      if(Q[j]<Q[i])k=j;
    
 
      Temp=Q[k];
      Q[k]=Q[i];
      Q[i]=Temp;
    }
}

3、插入排序

//插入排序InsertionSort
//起始队列长度为1,每次队列长度加1
//通过元素移动,将队列调整为有序状态
//时间复杂度:O(N^2)
//空间复杂度:O(N)
//稳定性:稳定
//输入:要排序的数组,数组长度
//输出:void,Q[]将处于排序状态
void InsertionSort(int Q[], int N)
{
  int i,j;
  int Temp;
  for(i=1;i<N;i++)
    {
      Temp = Q[i];
      for(j=i;j>0 && Q[j-1]>Temp;j--)
    {
      Q[j]=Q[j-1];
    }
 
      Q[j]=Temp;
    }
}

4、希尔排序

//希尔排序ShellSort
//指定一个步长,将需要排序的数字,按序号%步长分组
//对每组进行插入排序,然后减小步长,再次分组,排序直到步长为1结束
//时间复杂度:O(n^2)
//空间复杂度:O(n)
//稳定性:稳定
//输入:要排序的数组,数组长度
//输出:void,Q[]将处于排序状态
void ShellSort(int Q[], int N)
{
  int i,j;
  int Temp;
  int Step;
 
  for(Step=N/2;Step>0;Step=Step/2)
    {
      for(i=Step;i<N;i++)
    {
      Temp = Q[i];
      for(j=i;j>=Step && Q[j-Step]>Temp;j=j-Step)
        {
          Q[j]=Q[j-Step];
        }
      Q[j]=Temp;
    }
      //dumpArray(Q,N);
    }
}

5、归并排序

//归并排序MergeSort
//二路归并首先将归并长度定为2,在归并集内进行排序
//然后归并长度×2,将有序集合进行归并
//时间复杂度:O(NlogN)
//空间复杂度:O(N)
//稳定性:稳定
//输入:要排序的数组,数组长度
//输出:void,Q[]将处于排序状态
void Merge(int Q[],int TempArray[], int left, int mid, int right)
{
  int i=left,j=mid,k=left;
 
  while(i<mid && j<=right)
    {
      if(Q[i]>Q[j])
    {
      TempArray[k++]=Q[j++];
    }
      else
    {
      TempArray[k++]=Q[i++];
    }
    }
 
  while(i<mid)
    {
      TempArray[k++]=Q[i++];
    }
 
  while(j<=right)
    {
          TempArray[k++]=Q[j++];
    }
 
  for(k=left;k<=right;k++)
    {
      Q[k]=TempArray[k];
    }
 
}
 
void MSort(int Q[],int TempArray[], int left, int right)
{
  int center;
 
  if(left<right)
    {
      center=(left+right)/2;
      MSort(Q,TempArray,left,center);
      MSort(Q,TempArray,center+1,right);
      Merge(Q,TempArray,left,center+1,right);
    }
}
 
void MergeSort(int Q[], int N)
{
  int *TempArray = malloc(N*sizeof(int));
 
  if(TempArray!=NULL)
    {
      MSort(Q,TempArray,0,N-1);
    }
  else
    {
      //Todo: deal with not enough memory
      //RaiseError("MergeSort: not enough memory");
    }
}