www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - #import mapi.h

reply Martin Tschierschke <mt smartdolphin.de> writes:
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.
Mar 21 2018
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
Martin Tschierschke wrote:

 or tutorial
ok, tutorial: 1. learn C. 2. learn D. 3. DO IT! ;-)
Mar 21 2018
prev sibling next sibling parent reply Timoses <timosesu gmail.com> writes:
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
Mar 21 2018
parent reply Martin Tschierschke <mt smartdolphin.de> writes:
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 :-)
Mar 22 2018
parent Martin Tschierschke <mt smartdolphin.de> writes:
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", 50000, "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...
Mar 22 2018
prev sibling next sibling parent reply nkm1 <t4nk074 openmailbox.org> writes:
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... }
Mar 21 2018
parent Martin Tschierschke <mt smartdolphin.de> writes:
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*;
Mar 22 2018
prev sibling next sibling parent Kagamin <spam here.lot> writes:
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.
Mar 22 2018
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
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
Mar 22 2018
parent reply Martin Tschierschke <mt smartdolphin.de> writes:
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!
Mar 22 2018
parent reply Mike Parker <aldacron gmail.com> writes:
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.
Mar 22 2018
parent Martin Tschierschke <mt smartdolphin.de> writes:
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/hvanbsyrydsxpizltkca forum.dlang.org
Mar 23 2018