first commit
This commit is contained in:
commit
d2f10f3bbc
84 changed files with 13382 additions and 0 deletions
340
4_cppinterop.rst
Normal file
340
4_cppinterop.rst
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
======================
|
||||
Interfacing with C/C++
|
||||
======================
|
||||
|
||||
|
||||
Interfacing with C
|
||||
==================
|
||||
|
||||
2 options
|
||||
|
||||
- via ``dynlib``
|
||||
- via ``header``
|
||||
|
||||
|
||||
Dynlib import
|
||||
=============
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
type
|
||||
GtkWidget = object
|
||||
data: cint
|
||||
binary: cfloat
|
||||
compatible: char
|
||||
|
||||
proc gtk_image_new(): ptr GtkWidget
|
||||
{.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
|
||||
|
||||
|
||||
|
||||
Header import
|
||||
=============
|
||||
|
||||
.. code-block::
|
||||
:number-lines:
|
||||
|
||||
type
|
||||
GtkWidget {.importc: "GtkWidget_t", header: "<gtk.h>".} = object
|
||||
data {.importc: "Data".}: cint
|
||||
binary {.importc: "Binary".}: cfloat
|
||||
compatible: char
|
||||
|
||||
proc gtk_image_new(): ptr GtkWidget
|
||||
{.cdecl, header: "<gtk.h>", importc.}
|
||||
|
||||
{.passC: staticExec("pkg-config --cflags gtk").}
|
||||
{.passL: staticExec("pkg-config --libs gtk").}
|
||||
|
||||
|
||||
|
||||
Header import
|
||||
=============
|
||||
|
||||
.. code-block::
|
||||
:number-lines:
|
||||
|
||||
proc printf(formatstr: cstring)
|
||||
{.header: "<stdio.h>", importc: "printf", varargs.}
|
||||
|
||||
printf("%s%s", "Nim strings ", "converted to cstring for you")
|
||||
|
||||
|
||||
Data exchange with C
|
||||
====================
|
||||
|
||||
================= ==========================================================
|
||||
C type Nim type
|
||||
================= ==========================================================
|
||||
``int`` ``cint``
|
||||
``unsigned long`` ``culong``
|
||||
``float`` ``cfloat``
|
||||
``int x[4]`` ``array[4, cint]``
|
||||
``int*`` ``ptr int``
|
||||
``char*`` ``cstring``
|
||||
``char**`` ``cstringArray = ptr array [0..ArrayDummySize, cstring]``
|
||||
================= ==========================================================
|
||||
|
||||
|
||||
Data exchange with C
|
||||
====================
|
||||
|
||||
.. code-block:: C
|
||||
:number-lines:
|
||||
|
||||
int sum(int* x, size_t len) {
|
||||
int result = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
result += x[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Data exchange with C
|
||||
====================
|
||||
|
||||
.. code-block:: C
|
||||
:number-lines:
|
||||
|
||||
int sum(int* x, size_t len) {
|
||||
int result = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
result += x[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
proc sum(x: ptr cint; len: int): cint
|
||||
{.importc: "sum", cdecl, header: "foo.h".}
|
||||
|
||||
proc callSum =
|
||||
var x = @[1.cint, 2, 3, 4]
|
||||
echo sum(addr x[0], x.len)
|
||||
|
||||
var y = [1.cint, 2, 3, 4]
|
||||
echo sum(addr y[0], y.len)
|
||||
|
||||
|
||||
|
||||
CodegenDecl pragma
|
||||
==================
|
||||
|
||||
|
||||
.. code-block:: nim
|
||||
:number-lines:
|
||||
|
||||
var
|
||||
a {.codegenDecl: "$# progmem $#".}: int
|
||||
|
||||
proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} =
|
||||
echo "realistic interrupt handler"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Wrapping C++
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int value;
|
||||
int GetValue() { return value; }
|
||||
int& SetValue(int x) { field = x; return &field; }
|
||||
};
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
type
|
||||
Foo* {.importcpp: "Foo", header: "file.h".} = object
|
||||
value*: cint
|
||||
|
||||
proc getValue*(this: var Foo): cint
|
||||
{.importcpp: "GetValue", header: "file.h".}
|
||||
proc setValue*(this: var Foo; x: cint): var cint
|
||||
{.importcpp: "SetValue", header: "file.h".}
|
||||
|
||||
|
||||
Wrapping C++
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int value;
|
||||
int GetValue() { return value; }
|
||||
int& SetValue(int x) { field = x; return &field; }
|
||||
};
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
type
|
||||
Foo* {.importcpp: "Foo", header: "file.h".} = object
|
||||
value*: cint
|
||||
|
||||
proc getValue*(this: var Foo): cint
|
||||
{.importcpp: "#.GetValue(@)", header: "file.h".}
|
||||
proc setValue*(this: var Foo; x: cint): var cint
|
||||
{.importcpp: "#.SetValue(@)", header: "file.h".}
|
||||
|
||||
|
||||
|
||||
Constructors
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int value;
|
||||
int GetValue() { return value; }
|
||||
int& SetValue(int x) { field = x; return &field; }
|
||||
|
||||
Foo(int x): field(x) {}
|
||||
};
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
type
|
||||
Foo* {.importcpp: "Foo", header: "file.h".} = object
|
||||
value*: cint
|
||||
|
||||
proc getValue*(this: var Foo): cint
|
||||
{.importcpp: "#.GetValue(@)", header: "file.h".}
|
||||
proc setValue*(this: var Foo; x: cint): var cint
|
||||
{.importcpp: "#.SetValue(@)", header: "file.h".}
|
||||
|
||||
proc constructFoo*(x: cint): Foo
|
||||
{.importcpp: "Foo(@)", header: "file.h".}
|
||||
|
||||
|
||||
Constructors
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
Foo foo = Foo(1, 2, 3);
|
||||
|
||||
auto foo = Foo(1, 2, 3);
|
||||
|
||||
|
||||
Constructors
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
Foo foo = Foo(1, 2, 3);
|
||||
// Calls copy constructor!
|
||||
auto foo = Foo(1, 2, 3);
|
||||
|
||||
|
||||
Constructors
|
||||
============
|
||||
|
||||
.. code-block:: C++
|
||||
:number-lines:
|
||||
|
||||
Foo foo = Foo(1, 2, 3);
|
||||
// Calls copy constructor!
|
||||
auto foo = Foo(1, 2, 3);
|
||||
|
||||
Foo foo(1, 2, 3);
|
||||
|
||||
|
||||
Constructors
|
||||
============
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
proc constructFoo*(x: cint): Foo
|
||||
{.importcpp: "Foo(@)", header: "file.h", constructor.}
|
||||
|
||||
|
||||
.. code-block:: nim
|
||||
:number-lines:
|
||||
|
||||
proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".}
|
||||
|
||||
let x = newFoo(3, 4)
|
||||
|
||||
|
||||
proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.}
|
||||
|
||||
|
||||
|
||||
Generics
|
||||
========
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: nim
|
||||
:number-lines:
|
||||
|
||||
type Input {.importcpp: "System::Input".} = object
|
||||
proc getSubsystem*[T](): ptr T
|
||||
{.importcpp: "SystemManager::getSubsystem<'*0>()", nodecl.}
|
||||
|
||||
let x: ptr Input = getSubsystem[Input]()
|
||||
|
||||
Produces:
|
||||
|
||||
.. code-block:: C
|
||||
:number-lines:
|
||||
|
||||
x = SystemManager::getSubsystem<System::Input>()
|
||||
|
||||
|
||||
|
||||
Emit pragma
|
||||
===========
|
||||
|
||||
.. code-block:: Nim
|
||||
:number-lines:
|
||||
|
||||
{.emit: """
|
||||
static int cvariable = 420;
|
||||
""".}
|
||||
|
||||
{.push stackTrace:off.}
|
||||
proc embedsC() =
|
||||
var nimVar = 89
|
||||
# use backticks to access Nim symbols within an emit section:
|
||||
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".}
|
||||
{.pop.}
|
||||
|
||||
embedsC()
|
||||
|
||||
|
||||
..
|
||||
A tour through the standard library
|
||||
-----------------------------------
|
||||
|
||||
- system module: basic arithmetic and IO
|
||||
- strutils module; Unicode module
|
||||
- OS and osproc modules
|
||||
- sequtils and algorithm
|
||||
- tables and sets
|
||||
- linked lists, queues
|
||||
|
||||
- watchpoints
|
||||
- tracing
|
||||
- lexer generation
|
||||
- ORM
|
||||
|
||||
|
||||
Questions?
|
||||
==========
|
||||
Loading…
Add table
Add a link
Reference in a new issue