<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Elyézer Rezende</title><link href="https://elyezer.com/" rel="alternate"></link><link href="https://elyezer.com/feeds/all.atom.xml" rel="self"></link><id>https://elyezer.com/</id><updated>2018-06-07T00:00:00-03:00</updated><subtitle></subtitle><entry><title>Running UI tests on Travis</title><link href="https://elyezer.com/running-ui-tests-on-travis/" rel="alternate"></link><published>2018-06-07T00:00:00-03:00</published><updated>2018-06-07T00:00:00-03:00</updated><author><name>Elyézer Rezende</name></author><id>tag:elyezer.com,2018-06-07:/running-ui-tests-on-travis/</id><summary type="html">&lt;p&gt;Travis allows you to run &lt;a class="reference external" href="https://docs.travis-ci.com/user/chrome"&gt;Chrome&lt;/a&gt; and
&lt;a class="reference external" href="https://docs.travis-ci.com/user/firefox"&gt;Firefox&lt;/a&gt; on their build environment
and those can be used to run UI tests using Selenium.&lt;/p&gt;
&lt;p&gt;Today we are going to see how to install &lt;cite&gt;chromedriver&lt;/cite&gt; and &lt;cite&gt;geckodriver&lt;/cite&gt; in
order to be able to run UI tests using &lt;a class="reference external" href="https://pytest-selenium.readthedocs.io"&gt;pytest-selenium&lt;/a&gt;. To run those tests …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Travis allows you to run &lt;a class="reference external" href="https://docs.travis-ci.com/user/chrome"&gt;Chrome&lt;/a&gt; and
&lt;a class="reference external" href="https://docs.travis-ci.com/user/firefox"&gt;Firefox&lt;/a&gt; on their build environment
and those can be used to run UI tests using Selenium.&lt;/p&gt;
&lt;p&gt;Today we are going to see how to install &lt;cite&gt;chromedriver&lt;/cite&gt; and &lt;cite&gt;geckodriver&lt;/cite&gt; in
order to be able to run UI tests using &lt;a class="reference external" href="https://pytest-selenium.readthedocs.io"&gt;pytest-selenium&lt;/a&gt;. To run those tests you will need to
have your web application running so that Travis can access it and this article
won't cover that.&lt;/p&gt;
&lt;p&gt;Assuming that you already have Travis setup for your project, the first step to
do is to enable the Chrome and Firefox addons. You can do that by adding the
following lines to your &lt;tt class="docutils literal"&gt;.travis.yml&lt;/tt&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;stable&lt;/span&gt;
  &lt;span class="nt"&gt;firefox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;latest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Those lines will make Travis make available both Chrome and Firefox but that
won't install neither &lt;cite&gt;chromedrive&lt;/cite&gt; and &lt;cite&gt;geckodriver&lt;/cite&gt; which are required to run
Selenium webdriver. To make the process of setting up them, let's create some
scripts.&lt;/p&gt;
&lt;p&gt;First create the &lt;tt class="docutils literal"&gt;setup_chromedriver.sh&lt;/tt&gt; script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; -euvo pipefail

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;LATEST_CHROMEDRIVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
curl -L -s -o /tmp/chromedriver.zip &lt;span class="s2"&gt;&amp;quot;https://chromedriver.storage.googleapis.com/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LATEST_CHROMEDRIVER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/chromedriver_linux64.zip&amp;quot;&lt;/span&gt;
mkdir &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/chromedriver&amp;quot;&lt;/span&gt;
unzip /tmp/chromedriver.zip -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/chromedriver&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The script is checking for the latest &lt;cite&gt;chromedriver&lt;/cite&gt; and downloading it. Next
it creates a diretory where the &lt;tt class="docutils literal"&gt;chromedriver&lt;/tt&gt; executable will be placed. We
are creating a directory because later we will be adding that directory to the
&lt;tt class="docutils literal"&gt;PATH&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Next is time to create the &lt;tt class="docutils literal"&gt;setup_geckodriver.sh&lt;/tt&gt; script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; -euvo pipefail

curl -L -s -o geckodriverrelease https://api.github.com/repos/mozilla/geckodriver/releases/latest

cat &amp;gt; parser.py &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;import sys, json&lt;/span&gt;
&lt;span class="s"&gt;r = json.load(sys.stdin)&lt;/span&gt;
&lt;span class="s"&gt;if &amp;#39;assets&amp;#39; in r:&lt;/span&gt;
&lt;span class="s"&gt;    print([a for a in r[&amp;#39;assets&amp;#39;] if &amp;#39;linux64&amp;#39; in a[&amp;#39;name&amp;#39;]][0][&amp;#39;browser_download_url&amp;#39;]);&lt;/span&gt;
&lt;span class="s"&gt;else:&lt;/span&gt;
&lt;span class="s"&gt;    print(&amp;#39;https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz&amp;#39;)&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GECKODRIVER_DOWNLOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat geckodriverrelease &lt;span class="p"&gt;|&lt;/span&gt; python parser.py&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
curl -L -s -o /tmp/geckodriver.tar.gz &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GECKODRIVER_DOWNLOAD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

mkdir &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/geckodriver&amp;quot;&lt;/span&gt;
tar xvf /tmp/geckodriver.tar.gz -C &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/geckodriver&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, to install the latest &lt;cite&gt;geckodriver&lt;/cite&gt; it requires some extra
logic. See below a detailed explanation about why that is required.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;geckodriver&lt;/cite&gt; is hosted on Github and you can get the latest release
information using Github's API. The script is fetching that information by
doing an unauthenticated request. The problem with unauthenticated requests to
Github's API is that it limits, currently, to 60 requests per hour. Even though
your project's tests may run once a day you can hit that request limit because
the Travis environment is shared.&lt;/p&gt;
&lt;p&gt;To avoid the hitting the request rate limit and to parse the information about
the latest limit the script is creating the &lt;tt class="docutils literal"&gt;parser.py&lt;/tt&gt; Python script that
will fetch the URL for the latest release by parsing the JSON response (saved
on &lt;tt class="docutils literal"&gt;geckodriverrelease&lt;/tt&gt; file by curl) or default to the current latest
release URL if the Github API's rate limite is hit.&lt;/p&gt;
&lt;p&gt;After fetching the proper URL to download the latest &lt;cite&gt;geckodriver&lt;/cite&gt; the script
go ahead and get it and place it on the created &lt;tt class="docutils literal"&gt;geckodriver&lt;/tt&gt; directory. Same
as &lt;cite&gt;chromedriver&lt;/cite&gt; this directory will be added later to the &lt;tt class="docutils literal"&gt;PATH&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;With all that in place, it is time to edit the &lt;tt class="docutils literal"&gt;.travis.yml&lt;/tt&gt; file again and
make it run the UI tests. In the example we are going to see here, both setup
scripts were placed into a &lt;tt class="docutils literal"&gt;scripts&lt;/tt&gt; directory on the projects repository's
root directory.&lt;/p&gt;
&lt;p&gt;To make it more visually appealing on Travis let's run UI tests using &lt;a class="reference external" href="https://docs.travis-ci.com/user/build-stages/"&gt;build
stages&lt;/a&gt;. Below are the
definitions for the jobs to run tests using both Chrome and Firefox on
separated jobs. The environment variable &lt;tt class="docutils literal"&gt;NAME&lt;/tt&gt; is there just provide context
on Travis UI since you can't set jobs name as of now. On the &lt;tt class="docutils literal"&gt;before_install&lt;/tt&gt;
section of each job is where &lt;cite&gt;chromedriver&lt;/cite&gt; and &lt;cite&gt;geckodriver&lt;/cite&gt; are setup and the
executables are added to the &lt;tt class="docutils literal"&gt;PATH&lt;/tt&gt;. Finally the tests are running on the
&lt;tt class="docutils literal"&gt;script&lt;/tt&gt; section using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xvfb-run&lt;/span&gt;&lt;/tt&gt; which is required to run the browsers in
headless mode.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;test-ui&lt;/span&gt;
  &lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;NAME=ui-chrome&lt;/span&gt;
  &lt;span class="nt"&gt;before_install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;./scripts/setup_chromedriver.sh&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;export PATH=&amp;quot;${HOME}/chromedriver:${PATH}&amp;quot;&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;chromedriver --version&lt;/span&gt;
  &lt;span class="nt"&gt;install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;make run-web-app&lt;/span&gt;
  &lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;xvfb-run py.test -v --driver Chrome path/to/ui/tests&lt;/span&gt;

&lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;test-ui&lt;/span&gt;
  &lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;NAME=ui-firefox&lt;/span&gt;
  &lt;span class="nt"&gt;before_install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;./scripts/setup_geckodriver.sh&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;export PATH=&amp;quot;${HOME}/geckodriver:${PATH}&amp;quot;&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;geckodriver --version&lt;/span&gt;
  &lt;span class="nt"&gt;install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;make run-web-app&lt;/span&gt;
  &lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;xvfb-run py.test -v --driver Firefox path/to/ui/tests&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After all that you should be able to run UI tests on Travis. If you want a full
&lt;tt class="docutils literal"&gt;.travis.yml&lt;/tt&gt; example you can check &lt;a class="reference external" href="https://github.com/cloudigrade/integrade/blob/master/.travis.yml"&gt;integrade's .travis.yml&lt;/a&gt;.&lt;/p&gt;
</content><category term="Quality Engineering"></category><category term="pytest pytest-selenium python"></category></entry><entry><title>Using a C shared library with Python's ctypes module</title><link href="https://elyezer.com/using-a-c-shared-library-with-pythons-ctypes-module/" rel="alternate"></link><published>2018-03-09T00:00:00-03:00</published><updated>2018-03-09T00:00:00-03:00</updated><author><name>Elyézer Rezende</name></author><id>tag:elyezer.com,2018-03-09:/using-a-c-shared-library-with-pythons-ctypes-module/</id><summary type="html">&lt;p&gt;To demonstrate how to create a shared C library and using it with Python's
&lt;a class="reference external" href="https://docs.python.org/3/library/ctypes.html"&gt;ctypes&lt;/a&gt; library we are going to create a shared C library. First create the C
header file &lt;cite&gt;mean.h&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Returns the mean of passed parameters&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next create the C file &lt;cite&gt;mean.c …&lt;/cite&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;To demonstrate how to create a shared C library and using it with Python's
&lt;a class="reference external" href="https://docs.python.org/3/library/ctypes.html"&gt;ctypes&lt;/a&gt; library we are going to create a shared C library. First create the C
header file &lt;cite&gt;mean.h&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Returns the mean of passed parameters&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next create the C file &lt;cite&gt;mean.c&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;quot;mean.h&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can create the shared C library by compiling it using &lt;cite&gt;gcc&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gcc -shared -o libmean.so.1 mean.c
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally we can import the shared C library using the ctypes Python module,
consider the following interative shell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ctypes&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libmean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CDLL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./libmean.so.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# loads the shared library&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libmean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;restype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt; &lt;span class="c1"&gt;# define mean function return type&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libmean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# call mean function needs cast arg types&lt;/span&gt;
&lt;span class="mf"&gt;6.5&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libmean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argtypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctypes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# define arguments types&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;libmean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# call mean function does not need cast arg types&lt;/span&gt;
&lt;span class="mf"&gt;6.5&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libmean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# returned value is converted to python types&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nc"&gt;float&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This was tested using Python 3.6.4 and gcc 7.3.1 on Fedora 27. Check the
&lt;a class="reference external" href="https://docs.python.org/3/library/ctypes.html"&gt;ctypes&lt;/a&gt; documentation for more information.&lt;/p&gt;
</content><category term="Python"></category><category term="python"></category></entry></feed>