Skip to content

Commit

Permalink
Wrap the GMT_Destroy_Session function
Browse files Browse the repository at this point in the history
It's needed to free the memory from a session before a new one is
created and used.

Fixes #16
  • Loading branch information
leouieda committed Jul 5, 2017
1 parent 252d5df commit ecc2ad1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
6 changes: 5 additions & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ Low-level wrappers for the GMT C API
The GMT C API is accessed using ctypes_. The ``gmt.clib`` module offers
functions and classes that wrap the C API with a pythonic interface.

Most interactions with the C API are done through the
:func:`gmt.clib.call_module` function.

.. autosummary::
:toctree: api/
:template: function.rst

gmt.clib.create_session
gmt.clib.call_module
gmt.clib.create_session
gmt.clib.destroy_session
gmt.clib.load_libgmt


Expand Down
2 changes: 1 addition & 1 deletion gmt/clib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Low-level wrappers for the GMT C API using ctypes
"""
from .functions import create_session, call_module
from .functions import create_session, destroy_session, call_module
from .utils import load_libgmt
28 changes: 28 additions & 0 deletions gmt/clib/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def create_session():
It is a C void pointer containing the current session information and
cannot be accessed directly.
Remember to terminate the current session using
:func:`gmt.clib.destroy_session` before creating a new one.
Returns
-------
api_pointer : C void pointer (returned by ctypes as an integer)
Expand All @@ -37,13 +40,38 @@ def create_session():
return session


def destroy_session(session):
"""
Terminate and free the memory of a registered ``GMTAPI_CTRL`` session.
The session is created and consumed by the C API modules and needs to be
freed before creating a new. Otherwise, some of the configuration files
might be left behind and can influence subsequent API calls.
Parameters
----------
session : C void pointer (returned by ctypes as an integer)
The active session object produced by :func:`gmt.clib.create_session`.
"""
libgmt = load_libgmt()
c_destroy_session = libgmt.GMT_Destroy_Session
c_destroy_session.argtypes = [ctypes.c_void_p]
c_destroy_session.restype = ctypes.c_int
status = c_destroy_session(session)
assert status is not None, 'Failed returning None.'
assert status == 0, 'Failed with status code {}.'.format(status)


def call_module(session, module, args):
"""
Call a GMT module with the given arguments.
Makes a call to ``GMT_Call_Module`` from the C API using mode
"GMT_MODULE_CMD" (arguments passed as a single string).
Most interactions with the C API are done through this function.
Parameters
----------
session : ctypes.c_void_p
Expand Down
16 changes: 11 additions & 5 deletions gmt/tests/test_clib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import os

from ..clib import create_session, call_module, load_libgmt
from ..clib import create_session, destroy_session, call_module, load_libgmt


def test_load_libgmt():
Expand All @@ -12,10 +12,15 @@ def test_load_libgmt():
assert hasattr(libgmt, 'GMT_Create_Session')


def test_create_session():
"Test that create_session is called without errors"
session = create_session()
assert session is not None
def test_clib_session_management():
"Test that create and destroy session are called without errors"
session1 = create_session()
assert session1 is not None
session2 = create_session()
assert session2 is not None
assert session2 != session1
destroy_session(session1)
destroy_session(session2)


def test_call_module():
Expand All @@ -24,6 +29,7 @@ def test_call_module():
args = '-R10/70/-3/8 -JX4i/3i -Ba -P ->tmp.ps'
session = create_session()
call_module(session, module, args)
destroy_session(session)
assert os.path.exists('tmp.ps')
os.remove('tmp.ps')
# Not the most ideal test. Just check if no segfaults or exceptions occur.

0 comments on commit ecc2ad1

Please sign in to comment.