Skip to content

Commit

Permalink
Add C DLL Example
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Hamilton committed Apr 28, 2015
1 parent 91f60e8 commit 506741f
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -4,3 +4,6 @@ Kdb+ Database Examples
This repo contains associated code for the [kdb+ guides](http://www.timestored.com/kdb-guides) from TimeStored.com.

If you find them useful, consider taking one of our [kdb+ Training Courses](http://www.timestored.com/kdb-training/).

* Writing a [kdb C dll](http://www.timestored.com/kdb-guides/compile-load-c-dll) [Code](c-dll-example)
* QUnit [Unit Testing kdb](http://www.timestored.com/kdb-guides/kdb-regression-unit-tests) [Code](qunit)
3 changes: 3 additions & 0 deletions c-dll-example/comprun.bat
@@ -0,0 +1,3 @@
CALL "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64
cl /LD /DKXVER=3 mymoving.c mymoving.def q.lib
q load-functions.q
142 changes: 142 additions & 0 deletions c-dll-example/k.h
@@ -0,0 +1,142 @@
#ifndef KX
#define KX
typedef char*S,C;typedef unsigned char G;typedef short H;typedef int I;typedef long long J;typedef float E;typedef double F;typedef void V;
#ifdef __cplusplus
extern"C"{
#endif
#ifndef KXVER
#error "Set KXVER=3 for kdb+3.0 or standalone c-api after 2011-04-20. Otherwise set KXVER=2"
#endif
#if KXVER>=3
typedef struct k0{signed char m,a,t;C u;I r;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{J n;G G0[1];};};}*K;
typedef struct{G g[16];}U;
#define kU(x) ((U*)kG(x))
#define xU ((U*)xG)
extern K ku(U),ktn(I,J),kpn(S,J);
#define DO(n,x) {J i=0,_i=(n);for(;i<_i;++i){x;}}
#else
typedef struct k0{I r;H t,u;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{I n;G G0[1];};};}*K;
extern K ktn(I,I),kpn(S,I);
#define DO(n,x) {I i=0,_i=(n);for(;i<_i;++i){x;}}
#endif
#ifdef __cplusplus
}
#endif
//#include<string.h>
// vector accessors, e.g. kF(x)[i] for float&datetime
#define kG(x) ((x)->G0)
#define kC(x) kG(x)
#define kH(x) ((H*)kG(x))
#define kI(x) ((I*)kG(x))
#define kJ(x) ((J*)kG(x))
#define kE(x) ((E*)kG(x))
#define kF(x) ((F*)kG(x))
#define kS(x) ((S*)kG(x))
#define kK(x) ((K*)kG(x))

// type bytes qtype ctype accessor
#define KB 1 // 1 boolean char kG
#define UU 2 // 16 guid U kU
#define KG 4 // 1 byte char kG
#define KH 5 // 2 short short kH
#define KI 6 // 4 int int kI
#define KJ 7 // 8 long long kJ
#define KE 8 // 4 real float kE
#define KF 9 // 8 float double kF
#define KC 10 // 1 char char kC
#define KS 11 // * symbol char* kS

#define KP 12 // 8 timestamp long kJ (nanoseconds from 2000.01.01)
#define KM 13 // 4 month int kI (months from 2000.01.01)
#define KD 14 // 4 date int kI (days from 2000.01.01)

#define KN 16 // 8 timespan long kJ (nanoseconds)
#define KU 17 // 4 minute int kI
#define KV 18 // 4 second int kI
#define KT 19 // 4 time int kI (millisecond)

#define KZ 15 // 8 datetime double kF (DO NOT USE)

// table,dict
#define XT 98 // x->k is XD
#define XD 99 // kK(x)[0] is keys. kK(x)[1] is values.

#ifdef __cplusplus
extern"C"{
#endif
extern I khpun(const S,I,const S,I),khpu(const S,I,const S),khp(const S,I),ymd(I,I,I),dj(I);extern V r0(K),sd0(I),m9(),kclose(I);extern S sn(S,I),ss(S);
extern K ktj(I,J),ka(I),kb(I),kg(I),kh(I),ki(I),kj(J),ke(F),kf(F),kc(I),ks(S),kd(I),kz(F),kt(I),sd1(I,K(*)(I)),dl(V*f,I),
knk(I,...),kp(S),ja(K*,V*),js(K*,S),jk(K*,K),k(I,const S,...),xT(K),xD(K,K),ktd(K),r1(K),krr(const S),orr(const S),dot(K,K),b9(I,K),d9(K);
#ifdef __cplusplus
}
#endif

// nulls(n?) and infinities(w?)
#define nh ((I)0xFFFF8000)
#define wh ((I)0x7FFF)
#define ni ((I)0x80000000)
#define wi ((I)0x7FFFFFFF)
#define nj ((J)0x8000000000000000LL)
#define wj 0x7FFFFFFFFFFFFFFFLL
#ifdef WIN32
#define nf (log(-1.0))
#define wf (-log(0.0))
#define isnan _isnan
#define finite _finite
extern double log();
#else
#define nf (0/0.0)
#define wf (1/0.0)
#define closesocket(x) close(x)
#endif

// remove more clutter
#define O printf
#define R return
#define Z static
#define P(x,y) {if(x)R(y);}
#define U(x) P(!(x),0)
#define SW switch
#define CS(n,x) case n:x;break;
#define CD default

#define ZV Z V
#define ZK Z K
#define ZH Z H
#define ZI Z I
#define ZJ Z J
#define ZE Z E
#define ZF Z F
#define ZC Z C
#define ZS Z S

#define K1(f) K f(K x)
#define K2(f) K f(K x,K y)
#define TX(T,x) (*(T*)((G*)(x)+8))
#define xr x->r
#define xt x->t
#define xu x->u
#define xn x->n
#define xx xK[0]
#define xy xK[1]
#define xg TX(G,x)
#define xh TX(H,x)
#define xi TX(I,x)
#define xj TX(J,x)
#define xe TX(E,x)
#define xf TX(F,x)
#define xs TX(S,x)
#define xk TX(K,x)
#define xG x->G0
#define xH ((H*)xG)
#define xI ((I*)xG)
#define xJ ((J*)xG)
#define xE ((E*)xG)
#define xF ((F*)xG)
#define xS ((S*)xG)
#define xK ((K*)xG)
#define xC xG
#define xB ((G*)xG)

#endif

8 changes: 8 additions & 0 deletions c-dll-example/load-functions.q
@@ -0,0 +1,8 @@
/ from the DLL mymoving load the functions and assign to named variables
/ The 2: is used for loading
/ 2 at the end specifies the number of arguments
mysum:`mymoving 2:(`mysum;2)
myavg:`mymoving 2:(`myavg;2)

show "myavg[3; 6 7 5 8 2.]";
myavg[3; 6 7 5 8 2.]
75 changes: 75 additions & 0 deletions c-dll-example/mymoving.c
@@ -0,0 +1,75 @@
// TimeStored.com example of windows DLL
// http://www.timestored.com/kdb-guides/compile-load-c-dll

#include"k.h"
#include <float.h>

// Find the moving sum for a given window size and array of nums
K mysum(K window, K nums) {

long wsize = window->j;
long i=0;
K res = ktn(KF, nums->n);
double total;

F* resf = kF(res);
F* numsf = kF(nums);

// check type is float
if( (nums->t != KF) || (window->t != -KJ)) {
printf("invalid params");
return krr("wrong type params");
}

total = numsf[0];
resf[0] = total;
for(i=1; i < wsize; i++) {
total += numsf[i];
resf[i]=total;
}

for(i=wsize; i < nums->n; i++) {
total = total - numsf[i-wsize]+numsf[i];
resf[i]=total;
}

return res;
}


// Find the moving average for a given window size and array of nums
K myavg(K window, K nums) {

// initialize variables
long wsize = window->j;
long i=0;
K res = ktn(KF, nums->n);
double total;
long count;

F* resf = kF(res);
F* numsf = kF(nums);

// check type is float
if( (nums->t != KF) || (window->t != -KJ)) {
printf("invalid params");
return krr("wrong type params");
}

// find moving average of first window (special case)
total = numsf[0];
resf[0] = total;
count = 2;
for(i=1; i < wsize; i++) {
total += numsf[i];
resf[i] = total / count++;
}

// move window along by adding next number and removing earliest from average.
for(i=wsize; i < nums->n; i++) {
total = total - numsf[i-wsize]+numsf[i];
resf[i] = total / wsize;
}

return res;
}
3 changes: 3 additions & 0 deletions c-dll-example/mymoving.def
@@ -0,0 +1,3 @@
EXPORTS
mysum
myavg
Binary file added c-dll-example/q.lib
Binary file not shown.
11 changes: 11 additions & 0 deletions c-dll-example/readme.md
@@ -0,0 +1,11 @@
Calling C code from kdb+
======================================

The code demonstrates [compiling and loading a c dll for kdb](http://www.timestored.com/kdb-guides/compile-load-c-dll).

It shows how to:
- Compile a DLL on windows
- Load the library within kdb
- Calling the C function from kdb

It is a simple example only and does not contain good logging, argument checking etc.

0 comments on commit 506741f

Please sign in to comment.