Re: #import mapi.h

2018-03-23 Thread Martin Tschierschke via Digitalmars-d-learn

On Friday, 23 March 2018 at 01:12:58 UTC, Mike Parker wrote:
On Thursday, 22 March 2018 at 21:45:40 UTC, Martin Tschierschke 
wrote:

On Thursday, 22 March 2018 at 17:42:46 UTC, Paul Backus wrote:
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin 
Tschierschke wrote:
Is there an step by step introduction how to convert a C 
header of an external lib into the right extern(C){} block?


In addition to what others have said, I found the following 
article on the D Wiki useful:


https://wiki.dlang.org/D_binding_for_C


Thank you, this one is very good!


If you have Learning D, chapter 9 is all about interface D with 
C.


I will look at it! I have seen your hint already, you have 
mentioned it in the beginning of your blogpost. The discussion in 
an other thread [1] about direct integration of an C/C++ 
preprocessor into the D complier(s) is very interesting, I think 
this will push the adoption of the language, because you just can 
start immediately to use D as a replacement for C or C++. It is 
very fascinating to see how D is evolving all the time. Now I 
hope that with the survey and more donations the D Foundation get 
the ability to push this even more.


[1] 
https://forum.dlang.org/post/hvanbsyrydsxpizlt...@forum.dlang.org




Re: #import mapi.h

2018-03-22 Thread Mike Parker via Digitalmars-d-learn
On Thursday, 22 March 2018 at 21:45:40 UTC, Martin Tschierschke 
wrote:

On Thursday, 22 March 2018 at 17:42:46 UTC, Paul Backus wrote:
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin 
Tschierschke wrote:
Is there an step by step introduction how to convert a C 
header of an external lib into the right extern(C){} block?


In addition to what others have said, I found the following 
article on the D Wiki useful:


https://wiki.dlang.org/D_binding_for_C


Thank you, this one is very good!


If you have Learning D, chapter 9 is all about interface D with C.


Re: #import mapi.h

2018-03-22 Thread Martin Tschierschke via Digitalmars-d-learn

On Thursday, 22 March 2018 at 17:42:46 UTC, Paul Backus wrote:
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin 
Tschierschke wrote:
Is there an step by step introduction how to convert a C 
header of an external lib into the right extern(C){} block?


In addition to what others have said, I found the following 
article on the D Wiki useful:


https://wiki.dlang.org/D_binding_for_C


Thank you, this one is very good!



Re: #import mapi.h

2018-03-22 Thread Paul Backus via Digitalmars-d-learn
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin Tschierschke 
wrote:
Is there an step by step introduction how to convert a C header 
of an external lib into the right extern(C){} block?


In addition to what others have said, I found the following 
article on the D Wiki useful:


https://wiki.dlang.org/D_binding_for_C


Re: #import mapi.h

2018-03-22 Thread Kagamin via Digitalmars-d-learn
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin Tschierschke 
wrote:
Is there an step by step introduction how to convert a C header 
of an external lib into the right extern(C){} block?


In short, they should be binary compatible: where is a pointer on 
C side, should be a pointer on D side, same for integer sizes, 
data layout an calling conventions.


Re: #import mapi.h

2018-03-22 Thread Martin Tschierschke via Digitalmars-d-learn
On Thursday, 22 March 2018 at 12:53:23 UTC, Martin Tschierschke 
wrote:

On Wednesday, 21 March 2018 at 17:12:07 UTC, Timoses wrote:

[...]

I got it, my first mini test with C bindings!
Important missing at first: (stderr)

import core.stdc.stdio : stderr, FILE;
and use of toStringz inside:  mapi_query(dbh, toStringz(q) )

After installing monetdb and starting the server with:
https://www.monetdb.org/Documentation/UserGuide/Tutorial

My minimal version of the example compiled with
dmd app.d -I /usr/local/lib/libmapi.so

(My dub.json is still incomplete so the linking failed.)

Here is the code: (only the minimum of mapi.h is icluded!)

```
 std.stdio;
import std.string;

/* interfacing winth monetdb #include mapi.h */
/* minimum to run code of example at: 
https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/MAPI */

import core.stdc.stdio : stderr,FILE;
import core.stdc.stdlib;

struct MapiStruct;
alias Mapi = MapiStruct*;

struct MapiStatement;
alias MapiHdl = MapiStatement*;

enum MOK = 0 ;

alias MapiMsg = int;

extern(System){
Mapi mapi_connect(const char* host, int port, const char* 
username, const char* password, const char* lang, const char* 
dbname);

MapiHdl mapi_query(Mapi mid, const char *cmd);
int mapi_fetch_row(MapiHdl hdl);
char *mapi_fetch_field(MapiHdl hdl, int fnr);
MapiMsg mapi_error(Mapi mid);
MapiMsg mapi_explain(Mapi mid, FILE* fd);
MapiMsg mapi_destroy(Mapi mid);
MapiMsg mapi_close_handle(MapiHdl hdl);
MapiMsg mapi_explain_result(MapiHdl hdl, FILE* fd);
MapiMsg mapi_next_result(MapiHdl hdl);
MapiMsg mapi_explain_query(MapiHdl hdl, FILE* fd);
char *mapi_result_error(MapiHdl hdl);
}


void die(Mapi dbh, MapiHdl hdl) {
  if (hdl != null) {
mapi_explain_query(hdl, stderr);
do {
  if (mapi_result_error(hdl) != null)
mapi_explain_result(hdl, stderr);
} while (mapi_next_result(hdl) == 1);
mapi_close_handle(hdl);
mapi_destroy(dbh);
  } else if (dbh != null) {
mapi_explain(dbh, stderr);
mapi_destroy(dbh);
  } else {
fprintf(stderr, "command failed\n");
  }
  exit(-1);
}


MapiHdl query(Mapi dbh, string q) {
  MapiHdl ret = null;
  if ((ret = mapi_query(dbh, toStringz(q) )) == null || 
mapi_error(dbh) != MOK)

die(dbh, ret);
  return(ret);
}

void update(Mapi dbh, string q) {
  MapiHdl ret = query(dbh, q);
  if (mapi_close_handle(ret) != MOK)
die(dbh, ret);
}

void main()
{

auto  dbh = mapi_connect("localhost", 5, "monetdb", 
"monetdb", "sql", "voc");

  writeln("DB-connect");
  update(dbh, "CREATE TABLE emp (name VARCHAR(20), age INT)");
  writeln("create");
  update(dbh, "INSERT INTO emp VALUES ('John', 23)");
  update(dbh, "INSERT INTO emp VALUES ('Mary', 22)");
auto hdl = query(dbh, "SELECT * FROM emp");
  while (mapi_fetch_row(hdl)) {
auto name = mapi_fetch_field(hdl, 0);
auto age = mapi_fetch_field(hdl, 1);
printf("%s is %s\n", name, age);
  }
}
```

Will try to make a complete binding available later...


Re: #import mapi.h

2018-03-22 Thread Martin Tschierschke via Digitalmars-d-learn

On Wednesday, 21 March 2018 at 17:12:07 UTC, Timoses wrote:
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin 
Tschierschke wrote:
Is there an step by step introduction how to convert a C 
header of an external lib into the right extern(C){} block?


A blog post or tutorial, or chapter in a D book? (I have those 
from Packt Publishing)


While googling I found this:
https://dlang.org/blog/2017/12/05/interfacing-d-with-c-getting-started/

Haven't read it yet, but might give you some more insight.

For automatic conversion I stumbled across Dstep which I so far 
like a lot:

https://github.com/jacob-carlborg/dstep


Thank you! I will have a look at both, an Mike Parker is pointing 
to his book, too,
so now together with the post  from "nkm1" I should be able to 
make it!


@ketmar, I learned C but the counter of years from that time was 
stored in a nibble and so I got an overflow...error :-)


Re: #import mapi.h

2018-03-22 Thread Martin Tschierschke via Digitalmars-d-learn

On Wednesday, 21 March 2018 at 18:42:43 UTC, nkm1 wrote:
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin 
Tschierschke wrote:

[...]


The easiest thing to do is to write a wrapper in C. The wrapper 
will include all necessary headers and provide some easy to use 
functions that you can call from D. Of course, you'll need to 
use a C compiler to compile it.
Anyway, this header looks very straightforwar, no particular 
tricks with the preprocessor. It should be something like this 
(untested, obviously):


[...]

Thank you!
Especially this was a missing link:

struct MapiStruct;
alias Mapi = MapiStruct*;


Re: #import mapi.h

2018-03-21 Thread nkm1 via Digitalmars-d-learn
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin Tschierschke 
wrote:
Is there an step by step introduction how to convert a C header 
of an external lib into the right extern(C){} block?


A blog post or tutorial, or chapter in a D book? (I have those 
from Packt Publishing)


(Especially I am trying to get this used with D:
Montetdb C-API 
https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/MAPI
With: 
https://github.com/snaga/monetdb/blob/master/clients/mapilib/mapi.h)


The page: https://dlang.org/spec/interfaceToC.html is known, 
but not detailed enough for me.


The easiest thing to do is to write a wrapper in C. The wrapper 
will include all necessary headers and provide some easy to use 
functions that you can call from D. Of course, you'll need to use 
a C compiler to compile it.
Anyway, this header looks very straightforwar, no particular 
tricks with the preprocessor. It should be something like this 
(untested, obviously):


import core.stdc.stdio : FILE;

enum
{
MAPI_AUTO  = 0,  /* automatic type detection */
MAPI_TINY  = 1,
MAPI_UTINY = 2,
MAPI_SHORT = 3,
MAPI_USHORT= 4,
MAPI_INT   = 5,
MAPI_UINT  = 6,
MAPI_LONG  = 7,
MAPI_ULONG = 8,
MAPI_LONGLONG  = 9,
MAPI_ULONGLONG = 10,
MAPI_CHAR  = 11,
MAPI_VARCHAR   = 12,
MAPI_FLOAT = 13,
MAPI_DOUBLE= 14,
MAPI_DATE  = 15,
MAPI_TIME  = 16,
MAPI_DATETIME  = 17,
MAPI_NUMERIC   = 18,
}

enum int PLACEHOLDER = '?';

enum
{
MAPI_SEEK_SET = 0,
MAPI_SEEK_CUR = 1,
MAPI_SEEK_END = 2,
}

enum
{
MAPI_TRACE  = 1,
MAPI_TRACE_LANG = 2,
}

alias MapiMsg = int;

enum
{
MOK =  0,
MERROR  = -1,
MTIMEOUT= -2,
MMORE   = -3,
MSERVER = -4,
}

enum
{
LANG_MAL= 0,
LANG_SQL= 2,
LANG_JAQL   = 3,
}

/* prompts for MAPI protocol */
enum int PROMPTBEG = '\001'; /* start prompt bracket */

 /* prompt: ready for new query */
const(char)* PROMPT1 = "\001\001\n".ptr;

/* prompt: more data needed */
const(char)* PROMTP2 = "\001\002\n".ptr;

/*
 * The table field information is extracted from the table headers
 * obtained from the server. This list may be extended in the 
future.

 * The type of both the 'param' and 'binding'
 * variables refer to their underlying C-type. They are used for
 * automatic type coercion between back-end and application.
 */
struct MapiStruct;
alias Mapi = MapiStruct*;

/* this definition is a straight copy from 
sql/include/sql_query.h */

enum
{
Q_PARSE = 0,
Q_TABLE = 1,
Q_UPDATE= 2,
Q_SCHEMA= 3,
Q_TRANS = 4,
Q_PREPARE   = 5,
Q_BLOCK = 6,
}

struct MapiStatement;
alias MapiHdl = MapiStatement*;

alias mapi_uint64 = ulong;
alias mapi_int64 = long;

/* three structures used for communicating date/time information 
*/
/* these structs are deliberately compatible with the ODBC 
versions

   SQL_DATE_STRUCT, SQL_TIME_STRUCT, and SQL_TIMESTAMP_STRUCT */

/* used by MAPI_DATE */
struct MapiDate
{
short year;
ushort month;
ushort day;
}

/* used by MAPI_TIME */
struct MapiTime
{
ushort hour;
ushort minute;
ushort second;
}

/* used by MAPI_DATETIME */
struct MapiDateTime
{
short year;
ushort month;
ushort day;
ushort hour;
ushort minute;
ushort second;
uint fraction;  /* in 1000 millionths of a second (10e-9) */
}

/* connection-oriented functions */
extern (C)
{
Mapi mapi_mapi(const char *host,
   int port,
   const char *username,
   const char *password,
   const char *lang,
   const char *dbname);


// and so on...
}


Re: #import mapi.h

2018-03-21 Thread Timoses via Digitalmars-d-learn
On Wednesday, 21 March 2018 at 16:22:45 UTC, Martin Tschierschke 
wrote:
Is there an step by step introduction how to convert a C header 
of an external lib into the right extern(C){} block?


A blog post or tutorial, or chapter in a D book? (I have those 
from Packt Publishing)


While googling I found this:
https://dlang.org/blog/2017/12/05/interfacing-d-with-c-getting-started/

Haven't read it yet, but might give you some more insight.

For automatic conversion I stumbled across Dstep which I so far 
like a lot:

https://github.com/jacob-carlborg/dstep


Re: #import mapi.h

2018-03-21 Thread ketmar via Digitalmars-d-learn

Martin Tschierschke wrote:


or tutorial


ok, tutorial:

1. learn C.
2. learn D.
3. DO IT!

;-)


#import mapi.h

2018-03-21 Thread Martin Tschierschke via Digitalmars-d-learn
Is there an step by step introduction how to convert a C header 
of an external lib into the right extern(C){} block?


A blog post or tutorial, or chapter in a D book? (I have those 
from Packt Publishing)


(Especially I am trying to get this used with D:
Montetdb C-API 
https://www.monetdb.org/Documentation/Manuals/SQLreference/Programming/MAPI
With: 
https://github.com/snaga/monetdb/blob/master/clients/mapilib/mapi.h)


The page: https://dlang.org/spec/interfaceToC.html is known, but 
not detailed enough for me.