C++ Sort enemies by life

I have a problem with my little game which I have programmed, with the help of a c++ book.

I have a problem with my little game which I have programmed, with the help of a c++ book.

So first I have a class called PlayerObject, and a array with all game objects stored in. When the game starts, I loop through all the objects inside the array.

while (true) {
  for (auto i = 0; i < 100; i++) {
    auto object = FuncObjectId(i);
if (PlayerObject.IsEnemy(object) &amp;&amp;
    PlayerObject.Player.Position.Distance(object.Position) &lt; 1000) {
  // enemies found in range
  FuncMoveTo(object)
}

}
}

But what if there are several enemies in the given range? How can i order them ?

sorting by life or distance, for example. So that my player move to the closest target, or to the lowest health target.

Besides, the whole thing has to reset somehow. The player should not stop after killing the target, he should automatically go to the next enemy with the lowest life/closest position.

Go Top Programming Languages in 2020 from Authentic Surveys

Go Top Programming Languages in 2020 from Authentic Surveys

This article going to present the trends of top Programming Languages which will continue in the coming year 2020. This article uses data from authentic surveys, various collected statistics, search results and salary trends according to programming languages.

Comparing Programming Languages is a very complex thing and so there are many graphical illustration/jokes trying to symbolize Programming language. I found few and I am starting this article with those.

This is image title

In simple words, Programming Language empowers human to instruct and control machine. So, it is natural that there will be so many languages which try to make this process more powerful and simple. For this very reason there are hundreds of programming languages, many of those programming languages are now out of active use, few are going to be obsolete in coming years and then there are languages which is going to continue and prove its usage in coming years and then there are new programming language fighting for it acceptance.

This article going to present the trends of top Programming Languages which will continue in the coming year 2020. To predict the trend of the programming language in 2020 this article uses data from authentic surveys, various collected statistics, search results and salary trends according to programming languages. This article will help the new learner to pick a programming language to learn and for expert, it will help to decide either to switch to another language or to continue with his expertise language.

In the next section, I have prepared two tables which summarize the popularity trend of Programming Languages in the last five years (2015-19). The data is taken from Stackoverflow popularity survey 2015-2019. For a clear and accurate understanding, the programming languages are divided into two groups, first, languages which have origin before 2000 and the second group has languages which came after 2000. The selection of 2000 as the boundary is just random but very helpful to understand the programming trend under these two groups. The table also lists origin year and main or documented purpose of these programming/scripting languages.

This is image title
This is image title

Observations:

There is a decrease in the popularity of all languages from 2018 to 2019 except Python.

Python

Python is the only language continuously on rising since last five years. It is a general-purpose language, so someone wants to learn just one programming in 2020 and want to cover more area of software development then Python could be chosen**.**

Java

Java was on rising but fall in 2019, the reason could Kotlin gaining popularity on the Android platform. Java is a good choice for a programming language but now it is under Oracle and Google is promoting Kotlin so it is in the conflicted zone. As a matter of fact still, the large number of the company is using Java and going to continue with Java due to its developers base, framework, and legacy application.

C/C++

C and C++ are still holding with approx 20% and it will be there due to its inherent features and legacy system.

JavaScript

JavaScript popularity can be attributed to the growth of popular JavaScript library and framework like node.js, etc. JS is the language for the dynamic website and this going to be top for coming years because of its active development, support from Mozilla and penalty of libraries and frameworks. So, if someone wants to be web development, javascript is a must.

R

R is gaining popularity in recent years and reason would be growth and popularity of data analysis. It is used by data scientist but again much behind in comparison to Python which has established as general-purpose languages and enjoy active developers with lots of data science libraries and modules. So, one can prefer Python over R if they have to choose only one otherwise if wanted carrier in Data Sciences then learning both will a good option.

Ruby

Like PHP, Ruby is also facing tough competition from JavaScript and even Python to establish as back-end web development programming language. So, again for web development javascript and Python (server-side (Flask, Django, etc.) would be a good choice and will offer more domain flexibility than Ruby.

PHP

There is a sharp decline in PHP popularity in 2019 and it can be traced back to server-side acceptance of javascript and Python. So, if someone wants to go to server-side web development then still PHP is a good choice with a large number of popular framework like CakePHP, Codeigniter, etc. otherwise choosing a general-purpose programming language would be better.

Objective-C

Objective-C was the main language for Apple’s software such as macOS, iOS, etc. before Apple moved to Swift language. So this transition is reflected in the popularity of both languages, i.e. there is a fall in popularity for Objective-C and the popularity of Swift is rising. So, again if someone wants to be a developer for Apple’s products then Swift should be the language of choice.

This is image title

Observations:

Swift

Swift has replaced the Objective-C as the main language for Apple-related software and application. Since it is supported and promoted by Apple so there is an increase in popularity since its inception and as Apple is going to continue with it so if someone is looking for Apple-specific development platform then Swift is going to be a must-know programming language. This is mostly vendor and product-specific language with very less usage outside Apple’s eco-system.

Go

Go (Golang) is getting popularity as maintain, use and promoted by Google. The motivation of Go development was to address criticism of some of the popular languages and keeping the best of them in one place. Since 2017, Go is moving upward in popularity and with Google support, it is going to enjoy this in coming years. Google is also making Go as a primary language for new projects and replacing other languages with Go, this trend going to make useful and important to learn in coming years so one can pick Go as a new programming language.

Kotlin

Kotlin is being offered as an alternative of Java for Android development and again it is supported and promoted by Google so it is also picking up by developers and gaining popularity in recent years. So, with the growth of Android, support of Google and with clean and short syntax it is going to be a choice of Android application developers and is a good choice to learn for Android App developer. Kotlin going to be shine as a prominent programming environment for Android development.

Scala

Scala tries to establish as an alternative to Java but didn’t get very well among developers. It doesn’t have big support from any multi-national company, perceive as functional languages and dependency on JVM doesn’t provide much scope to rise in popularity. There could be steady growth but very slow and surely not a language to learn as a beginner.

Julia

Julia aims to bring the speed of ‘C’ and simplicity of Python but it is strange that didn’t found any popularity in Stackoverflow survey but gaining popularity among data science domain and being seen as a challenger for R and Python in long run. Surely, there will be growth in Julia but still, Python or R is better for job and growth.

C#

C# is the language for the .NET framework and developed by Microsoft. Its popularity is approx constant over past years and going to continue with a similar trend. This is vendor-specific language so one can pick this language if want to work in the Microsoft development environment. Recently, Microsoft has open-sourced the .NET so there would be some upward trend but again it is vendor-specific so there won’t be much affected.

Rust

Rust, Clojure, etc. are languages which have a user-base but not so popular so surely not going to have an upward swing in popularity.


A Picture Says a Thousand Words

To understand a clear trend and picture of top programming language growth let keep a picture of it by the various chart. The figure 1 and figure2 gives a very clear picture that in old language stack JavaScript is far ahead than others and credit goes to boom in web development, then C and C++ together competing very closer to Java. Python is moving upward in popularity and only language which popularity is constantly increasing in the last 5 years. New languages are getting popularity and most of them are supported by the multi-national company and bit IT giant like Microsoft, Google and Apple.

This is image title

This is image title

Loved and Wanted Languages

This is image title

This is image title

From above Table and Figure, few observations are very obvious, Love of Rust is growing in last five years whereas Swift is loosing love from developers and Python is in between these two and last two years have gain for Python. One more unique observation is that out of 5 loved languages 4 are from post 2000 group while only Python is the older language and Kotlin love started with addition of Kotlin for Android development post 2017.

This is image title

From above table, wish of developing in javascript and Python is growing in last years and this reflect in popularity and love for the language. There is a sharp decline in Java and this is due to the addition of Kotlin as alternative for Android app development and also change of policy by Oracle who own Java now.

This is image title

Technologies and Programming Languages

This is image title

In this figure, one can see that the largest cluster is for Web development and JavaScript and its various framework is dominating the cluster this is USP of JavaScript growth. The second-largest cluster is of Microsoft technologies and Python technologies which again clear the popularity and love for the language. Python cluster is linked with data science technologies which highlight the growth story of Python.

TIOBE Index

TIOBE index rank programming language based on search engine search result. The selection of search engines and programming language is defined in its page. The ratings are calculated by counting hits of the most popular search engines. The search query that is used is +” programming”. In TIOBE index Java is dominating the ranking in the last two decades where C is holding the 1st and 2nd rank for the last 30 years. Python has come a long way in the last two decades i.e. 24th in 1999 to 3rd in 2019. If someone merges the C and C++ then it would hold the 1st positions forever.

This is image title

In the new languages (post-2000), Rust moved up in ranking i.e. from 33rd to 28th, and Julia from 50th to 39th. It is also interesting to note that Kotlin doesn’t seem to come closer to the top 20.

Popularity of Programming Language (PYPL) Index

The PYPL index is created by analyzing how often language tutorials are searched on Google. The more a language tutorial is searched, the more popular the language is assumed to be. It is a leading indicator. The raw data comes from Google Trends.

Below Figure verifies that the top 3 languages are Python, Java, and JavaScript. C#, PHP, C/C++ also secure top position, this trend is again similar to stack-overflow, and TIOBE index.

This is image title

Above Figure indicates that among new programming Language i.e. post 2000 Kotlin, Go, Rust, and Julia is moving up in the ranking.

This is image title

Job Market and Salary

Salary depends upon the geographical area and demand of the products, a programming language based salary comparison is just a tool to predict or estimate the salary trend. We have summarized salary based on programming language from popular survey i.e. Dice salary survey 2018 and Stack-overflow survey 2018 and 2019.

This is image title

From the above table, it is very clear from both survey that Go/Golang is a very high paid job in the market and even stands 1st rank in a high paid job in stack-overflow 2019 survey and Dice Salary Survey 2018.

Language Predictability

So, as closing remarks, It is easy to predict a language trend but choosing only one language to learn is a really difficult choice and totally depend upon the individual choice and their future plans, for example, if you want to work in Web Development you can’t afford neglecting Javascript, if you want to work with Apple’s products you can’t neglect Swift now, if your taste is in system-level programming then C and C++ is your friend, Python makes you run faster in many domains and currently darling in Data science. You see each language takes you on a different journey. Choose your destination and then drive with the language of that path.

You may also like: Programming Languages - Trend Predictions in 2020 and Next Years.

We’ll love to know your opinion. What is the Best Programming Language for you?

Thank for reading! If you enjoyed this article, please share it with others who may enjoy it as well.!

How to Write Node.js Addons using C++ and N-API for Beginners

How to Write Node.js Addons using C++ and N-API for Beginners

This article will only focus on C++ addons for NodeJs using N-API. For this we will use the node-addon-api package from the N-API team which contains header-only C++ wrapper classes for the N-API. I suggest you follow through by coding live as you read.

Node.js Addons are dynamically-linked shared objects, written in C++, that can be loaded into Node.js using the [require()](https://nodejs.org/api/modules.html#modules_require) function, and used just as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries.

There can be many reasons to write nodejs addons:
1. You may want to access some native apis that is difficult using JS alone.
2. You may want to integrate a third party library written in C/C++ and use it directly in NodeJs.
3. You may want to rewrite some of the modules in C++ for performance reasons.
Whatever your reason is, this blog focuses on explaining the N-API and how you can use it to build C/C++ based NodeJS addons.

The complete source code from this blog is available at github

So, If you are not interested in reading through, you can directly take a look at the code there also.

What is N-API?

N-API (pronounced N as in the letter, followed by API) is an API for building native Addons. It is independent from the underlying JavaScript runtime (ex V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate Addons from changes in the underlying JavaScript engine and allow modules compiled for one version to run on later versions of Node.js without recompilation.

In essence , N-API can be used to build NodeJS Addons using C or C++. And the addons built using this would not break across different implementations or versions of NodeJS.

N-API is a stable API as of Node v10 (latest stable release when writing this article). N-API was experimental in Node v8 and v9.

To see a demo of N-API in action watch this youtube video:

This article will only focus on C++ addons for NodeJs using N-API. For this we will use the node-addon-api (github) package from the N-API team which contains header-only C++ wrapper classes for the N-API ( basically it provides C++ object model and exception handling semantics with low overhead).

Since this blog post covers very minimal theory, I suggest you follow through by coding live as you read.

Lets Code: Boilerplate setup

Create a basic node project test-addon

mkdir test-addon
cd test-addon
git init
npm init

Install the dependencies:

npm install node-gyp --save-dev
npm install node-addon-api

node-gyp is the toolchain to compile the addons.
node-addon-api is a helper project as described earlier that will make writing C++ addons easier.

In the package.json set the attribute gypfile:true and setup the following files as below:

node_modules
*.log
build
{
    "targets": [{
        "target_name": "testaddon",
        "cflags!": [ "-fno-exceptions" ],
        "cflags_cc!": [ "-fno-exceptions" ],
        "sources": [
            "cppsrc/main.cpp"
        ],
        'include_dirs': [
            "<[email protected](node -p \"require('node-addon-api').include\")"
        ],
        'libraries': [],
        'dependencies': [
            "<!(node -p \"require('node-addon-api').gyp\")"
        ],
        'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ]
    }]
}
{
  "name": "test-addon",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "gypfile": true,
  "scripts": {
    "build": "node-gyp rebuild",
    "clean": "node-gyp clean"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "node-gyp": "^3.7.0"
  },
  "dependencies": {
    "node-addon-api": "^1.3.0"
  }
}

binding.gyp file contains all the files that need to be compiled and all the include files / libraries that the project will be using. If you notice we have added cppsrc/main.cpp file as our source file.

Also our package.json mentions a index.js file as its main file.

Lets create both of them :

//index.js
const testAddon = require('./build/Release/testaddon.node');

module.exports = testAddon;
/* cppsrc/main.cpp */
#include <napi.h>

Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
  return exports;
}

NODE_API_MODULE(testaddon, InitAll)

The base boilerplate is complete. Lets try and build our addon

type npm run build

You should have an output similar to this:

npm run build
> [email protected] build /Users/atulr/Projects/Hobby/test-addon
> node-gyp rebuild
SOLINK_MODULE(target) Release/nothing.node
  CXX(target) Release/obj.target/testaddon/cppsrc/main.o
  SOLINK_MODULE(target) Release/testaddon.node

Wohoo ! compilation was successful. Lets run it !

Type node index.js . Sadly you will not get any output here.

Ideally you should use a debugger tool to debug and see what the contents of testAddon is but for demo here lets just add a console.log like this:

//index.js
const testAddon = require('./build/Release/testaddon.node');
console.log('addon',testAddon);
module.exports = testAddon;

Now run index.js again. You should see an output like this :

node index.js
addon {}

Awesome !! Now we have a working setup to start with.

Before we go ahead, lets take a look at cppsrc/main.cpp in detail:
1. #include<napi.h> includes the napi header file so that we can access all the helper macros, classes and functions.
2. NODE_API_MODULE is a macro that accepts modulename and registerfunction as parameters.
3. In our case registerfunction is InitAll and it takes two parameters which are passed by N-API. First parameter env is the context that needs to be passed on to most N-API function and exports is the object used to set the exported functions and classes via N-API.

The source code documentation for NODE_API_MODULE says:

/**
* This code defines the entry-point for the Node addon, it tells Node where to go
* once the library has been loaded into active memory. The first argument must
* match the "target" in our *binding.gyp*. Using NODE_GYP_MODULE_NAME ensures
* that the argument will be correct, as long as the module is built with
* node-gyp (which is the usual way of building modules). The second argument
* points to the function to invoke. The function must not be namespaced.
*/
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

To read in more depth you can visit the documentation of node-gyp here

Exporting a Hello World C++ function using N-API

Now lets add an example of exporting a C++ function to NodeJS.

Lets take an example of a simple function

std::string hello(){
  return "Hello World";
}

Lets try to export hello to Javascript side with our addon.

Create the following files: cppsrc/Samples/functionexample.h

#include <napi.h>
namespace functionexample {
  std::string hello();
  Napi::String HelloWrapped(const Napi::CallbackInfo& info);
  Napi::Object Init(Napi::Env env, Napi::Object exports);
}

The corresponding cppsrc/Samples/functionexample.cpp

#include "functionexample.h"
std::string functionexample::hello(){
  return "Hello World";
}
Napi::String functionexample::HelloWrapped(const Napi::CallbackInfo& info) 
{
  Napi::Env env = info.Env();
  Napi::String returnValue = Napi::String::New(env, functionexample::hello());
  
  return returnValue;
}
Napi::Object functionexample::Init(Napi::Env env, Napi::Object exports) 
{
  exports.Set(
"hello", Napi::Function::New(env, functionexample::HelloWrapped)
  );
 
  return exports;
}

Wow ! Looks like a lot. But if you look closely, its not as complex as it looks. For every function in C++ we want to export we will basically create a NAPI wrapped function (HelloWrapped in this example) and add it to the exports object using Init.

Lets take some time to understand HelloWrapped function. Every wrapped function that needs to be exported to JS should have input params/return value from the Napi namespace.
Every wrapped function takes in CallbackInfo as the input parameter. This contains things like the context and the input parameters that needs to be passed to the function.

Initfunction is used to just set the export key as hello with corresponding wrapped function HelloWrapped .

Now we need to make our node-gyp know that we have added extra c++ files. So make the following changes to binding.gyp,main.cpp and index.js

diff --git a/binding.gyp b/binding.gyp
index 23b9976..2d188af 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -4,7 +4,8 @@
         "cflags!": [ "-fno-exceptions" ],
         "cflags_cc!": [ "-fno-exceptions" ],
         "sources": [
-            "cppsrc/main.cpp"
+            "cppsrc/main.cpp",
+            "cppsrc/Samples/functionexample.cpp"
         ],
         'include_dirs': [
             "<[email protected](node -p \"require('node-addon-api').include\")"



diff --git a/cppsrc/main.cpp b/cppsrc/main.cpp
index f016c4e..f62ed77 100644
--- a/cppsrc/main.cpp
+++ b/cppsrc/main.cpp
@@ -1,7 +1,8 @@
 #include <napi.h>
+#include "Samples/functionexample.h"
 
 Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
-  return exports;
+  return functionexample::Init(env, exports);
 }
 
 NODE_API_MODULE(testaddon, InitAll)



diff --git a/index.js b/index.js
index 65f955e..e91b98f 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,4 @@
 const testAddon = require('./build/Release/testaddon.node');
 console.log('addon',testAddon);
+console.log(testAddon.hello());
 module.exports = testAddon;

Remember : Any change in c++ src files will need recompilation before you can use the changes in NodeJS. So make sure you run npm run build again after changing c++ files.

Also when you add a new header file/cpp file :
1. Add it to binding.gyp
2. Add it to main.cpp
3. Do npm rebuild and access it via JS.

Now run it ! node index.js .You should see the output as follows:

node index.js
addon { hello: [Function] }
Hello World

Voila ! Now we have a hello world from C++ world into JS World!

How about functions with input parameters ?

Lets say that the function that we want to export has both input and output params. For example:

int add(int a, int b){
  return a + b;
}

To add the function we will make the following changes:

diff --git a/cppsrc/Samples/functionexample.cpp b/cppsrc/Samples/functionexample.cpp
index 0bd9bc2..37b7eb9 100644
--- a/cppsrc/Samples/functionexample.cpp
+++ b/cppsrc/Samples/functionexample.cpp
@@ -4,13 +4,33 @@ std::string functionexample::hello(){
     return "Hello World";
 }
 
+int functionexample::add(int a, int b){
+  return a + b;
+}
+
 Napi::String functionexample::HelloWrapped(const Napi::CallbackInfo& info) {
     Napi::Env env = info.Env();
     Napi::String returnValue = Napi::String::New(env, functionexample::hello());
     return returnValue;
 }
 
+
+Napi::Number functionexample::AddWrapped(const Napi::CallbackInfo& info) {
+    Napi::Env env = info.Env();
+    if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
+        Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
+    } 
+
+    Napi::Number first = info[0].As<Napi::Number>();
+    Napi::Number second = info[1].As<Napi::Number>();
+
+    int returnValue = functionexample::add(first.Int32Value(), second.Int32Value());
+    
+    return Napi::Number::New(env, returnValue);
+}
+
 Napi::Object functionexample::Init(Napi::Env env, Napi::Object exports) {
     exports.Set("hello", Napi::Function::New(env, functionexample::HelloWrapped));
+    exports.Set("add", Napi::Function::New(env, functionexample::AddWrapped));
     return exports;
 }
 
 
diff --git a/cppsrc/Samples/functionexample.h b/cppsrc/Samples/functionexample.h
index 44563aa..e15aa7b 100644
--- a/cppsrc/Samples/functionexample.h
+++ b/cppsrc/Samples/functionexample.h
@@ -4,6 +4,10 @@ namespace functionexample {
 
     std::string hello();
     Napi::String HelloWrapped(const Napi::CallbackInfo& info);
-    Napi::Object Init(Napi::Env env, Napi::Object exports);
 
+    int add(int a, int b);
+    Napi::Number AddWrapped(const Napi::CallbackInfo& info);
+
+    Napi::Object Init(Napi::Env env, Napi::Object exports);
+    
 }
 
 
diff --git a/index.js b/index.js
index e91b98f..72860f8 100644
--- a/index.js
+++ b/index.js
@@ -1,4 +1,5 @@
 const testAddon = require('./build/Release/testaddon.node');
 console.log('addon',testAddon);
-console.log(testAddon.hello());
+console.log('hello ', testAddon.hello());
+console.log('add ', testAddon.add(5, 10));
 module.exports = testAddon;

Explanation:
1. We added a simple add function.
2. We added the wrapper for the add function : AddWrapped which is used to interface the add function with N-API.
3. We added the key add to export the AddWrapped function to the JS.

I believe the example is fairly straightforward and self explanatory. If more explanation is needed, let me know in the comments and I ll add more details here. Passing complex references and objects to the functions will be covered in the later sections below.

Output:

node index.js
addon { hello: [Function], add: [Function] }
hello  Hello World
add  15

Awesome !!

Exporting a Hello World C++ Class using N-API

Lets create a simple C++ class that stores a double value. The member functions are pretty self explanatory.

/* cppsrc/Samples/actualclass.cpp */

#include "actualclass.h"

ActualClass::ActualClass(double value){
    this->value_ = value;
}

double ActualClass::getValue()
{
  return this->value_;
}

double ActualClass::add(double toAdd)
{
  this->value_ += toAdd;
  return this->value_;
}
/* cppsrc/Samples/actualclass.h */

class ActualClass {
 public:
  ActualClass(double value); //constructor
  double getValue(); //getter for the value
  double add(double toAdd); //adds the toAdd value to the value_
 private:
  double value_;
};

I believe the above code is pretty straightforward and self explanatory.

To export this class to JS side we will need to create a wrapper class. Lets name the wrapper class as ClassExample .

Create the wrapper Class as follows: Please look at the classexample.h first and try to grasp the intent of the Wrapper class before going to the implementation.

/* cppsrc/Samples/classexample.cpp */

#include "classexample.h"

Napi::FunctionReference ClassExample::constructor;

Napi::Object ClassExample::Init(Napi::Env env, Napi::Object exports) {
  Napi::HandleScope scope(env);

  Napi::Function func = DefineClass(env, "ClassExample", {
    InstanceMethod("add", &ClassExample::Add),
    InstanceMethod("getValue", &ClassExample::GetValue),
  });

  constructor = Napi::Persistent(func);
  constructor.SuppressDestruct();

  exports.Set("ClassExample", func);
  return exports;
}

ClassExample::ClassExample(const Napi::CallbackInfo& info) : Napi::ObjectWrap<ClassExample>(info)  {
  Napi::Env env = info.Env();
  Napi::HandleScope scope(env);

  int length = info.Length();
  if (length != 1 || !info[0].IsNumber()) {
    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
  }

  Napi::Number value = info[0].As<Napi::Number>();
  this->actualClass_ = new ActualClass(value.DoubleValue());
}

Napi::Value ClassExample::GetValue(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::HandleScope scope(env);

  double num = this->actualClass_->getValue();
  return Napi::Number::New(env, num);
}


Napi::Value ClassExample::Add(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::HandleScope scope(env);

  if (  info.Length() != 1 || !info[0].IsNumber()) {
    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
  }

  Napi::Number toAdd = info[0].As<Napi::Number>();
  double answer = this->actualClass_->add(toAdd.DoubleValue());

  return Napi::Number::New(info.Env(), answer);
}
/* cppsrc/Samples/classexample.h */

#include <napi.h>
#include "actualclass.h"

class ClassExample : public Napi::ObjectWrap<ClassExample> {
 public:
  static Napi::Object Init(Napi::Env env, Napi::Object exports); //Init function for setting the export key to JS
  ClassExample(const Napi::CallbackInfo& info); //Constructor to initialise

 private:
  static Napi::FunctionReference constructor; //reference to store the class definition that needs to be exported to JS
  Napi::Value GetValue(const Napi::CallbackInfo& info); //wrapped getValue function 
  Napi::Value Add(const Napi::CallbackInfo& info); //wrapped add function
  ActualClass *actualClass_; //internal instance of actualclass used to perform actual operations.
};

Lets take a good look at the header file of our wrapper class classexample.h:

As mentioned before, Anything that needs to be exported to JS world needs to be wrapped with N-API. Hence:
1. First step is to create a wrapper class which extends Napi::ObjectWrap<ClassExample> .
2. Just like in case of functions we need a Init method to set the export key.
3. Except the static Napi::FunctionReference constructor; rest all the methods are self explanatory.

Now, lets take a look at the actual implementation classexample.cpp .
1. ClassExample::Init function is responsible to create and set the export key. Here we will export the class as ClassExample to the JS side.

Important part here is :

Napi::Function func = DefineClass(env, "ClassExample", 
{
  InstanceMethod("add", &ClassExample::Add),
  InstanceMethod("getValue", &ClassExample::GetValue),
});

func is used to define the class that will be exported to JS and then the func is assigned to constructor which is a static function reference in c++. This is where the earlier defined static Napi::FunctionReference constructor; comes in. Similar to InstanceMethod there are various methods defined in NAPI to export different types of class methods. For example: Static methods can be exported using StaticMethod .

If you are wondering what env is :

env is the environment that represent an independent instance of the JavaScript runtime,

I think of it as the js context that needs to be passed around to most NAPI functions as the first argument.

2. Now lets see the implementation of ClassExample::Add function.

Napi::Value ClassExample::Add(const Napi::CallbackInfo& info) 
{
  Napi::Env env = info.Env();
  Napi::HandleScope scope(env);
  
  if (info.Length() != 1 || !info[0].IsNumber()) {
     Napi::TypeError::New(env, "Numberexpected").ThrowAsJavaScriptException();
  }
  Napi::Number toAdd = info[0].As<Napi::Number>();
  double answer = this->actualClass_->add(toAdd.DoubleValue());
  return Napi::Number::New(info.Env(), answer);
}

Here input params are checked first using info from env. Now, to read a value from JS side we read it like info[0].As<Napi::Number>();. Since C++ is a strongly typed language and JS is not. We have to convert every value that we get from JS side to its appropriate type. After we convert the value we simply call the internal actualClass
instance and return the value. But since the value is a double we need to wrap it with a Napi::Number instance so that it can be passed to the JS side.

We are not done yet. Remember we need to now add entries to tell the compiler to compile the new source files we added.

diff --git a/binding.gyp b/binding.gyp
index 2d188af..031bf18 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -5,7 +5,9 @@
         "cflags_cc!": [ "-fno-exceptions" ],
         "sources": [
             "cppsrc/main.cpp",
-            "cppsrc/Samples/functionexample.cpp"
+            "cppsrc/Samples/functionexample.cpp",
+            "cppsrc/Samples/actualclass.cpp",
+            "cppsrc/Samples/classexample.cpp"
         ],
         'include_dirs': [
             "<[email protected](node -p \"require('node-addon-api').include\")"
             
             
diff --git a/cppsrc/main.cpp b/cppsrc/main.cpp
index f62ed77..2b739d3 100644
--- a/cppsrc/main.cpp
+++ b/cppsrc/main.cpp
@@ -1,8 +1,10 @@
 #include <napi.h>
 #include "Samples/functionexample.h"
+#include "Samples/classexample.h"
 
 Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
-  return functionexample::Init(env, exports);
+  functionexample::Init(env, exports);
+  return ClassExample::Init(env, exports);
 }
 
-NODE_API_MODULE(testaddon, InitAll)
+NODE_API_MODULE(NODE_GYP_MODULE_NAME, InitAll)


diff --git a/index.js b/index.js
index 72860f8..d849e0e 100644
--- a/index.js
+++ b/index.js
@@ -2,4 +2,9 @@ const testAddon = require('./build/Release/testaddon.node');
 console.log('addon',testAddon);
 console.log('hello ', testAddon.hello());
 console.log('add ', testAddon.add(5, 10));
+
+
+const classInstance = new testAddon.ClassExample(4.3);
+console.log('Testing class initial value : ',classInstance.getValue());
+console.log('After adding 3.3 : ',classInstance.add(3.3));
 module.exports = testAddon;

Make the above changes and run npm run build , followed by node index.js .

Notice that we have to both classexample.cpp and actualclass.cpp in the binding.gyp . The reason is that both classes are written by us. If you have a thrid party library c++ file. Then you would need to include the precompiled dynamic library in the libraries section of binding.gyp instead.

Output:

node index.js
addon { hello: [Function],
  add: [Function],
  ClassExample: [Function: ClassExample] }
hello  Hello World
add  15
Testing class initial value :  4.3
After adding 3.3 :  7.6

That was easy ! Isn’t it ?

This should be enough for most use cases. But if you need to know how to send class instances back/any complex object between JS and C++ read on.

Sending complex js objects to the C++ world

Lets say we have a use case like below:

const prevInstance = new testAddon.ClassExample(4.3);
console.log('Initial value : ', prevInstance.getValue());
console.log('After adding 3.3 : ', prevInstance.add(3.3));
const newFromExisting = new testAddon.ClassExample(prevInstance);
console.log('Testing class initial value for derived instance');
console.log(newFromExisting.getValue()); 

Here, we have an instance of ClassExample in prevInstance .

And we want a new instance newFromExisting which has same value of prevInstance. For that, we want to pass the existing instance prevInstance to the constructor of ClassExample . Since, prevInstance is not a primitive value like int, double etc. The expected output of the last console.log should be 7.6 .

Lets see how we can do that:

diff --git a/cppsrc/Samples/classexample.cpp b/cppsrc/Samples/classexample.cpp
index 8dfa3cc..834f7ea 100644
--- a/cppsrc/Samples/classexample.cpp
+++ b/cppsrc/Samples/classexample.cpp
@@ -22,8 +22,17 @@ ClassExample::ClassExample(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Cl
   Napi::HandleScope scope(env);
 
   int length = info.Length();
-  if (length != 1 || !info[0].IsNumber()) {
-    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
+  
+  if (length != 1) {
+    Napi::TypeError::New(env, "Only one argument expected").ThrowAsJavaScriptException();
+  }
+
+  if(!info[0].IsNumber()){
+    Napi::Object object_parent = info[0].As<Napi::Object>();
+    ClassExample* example_parent = Napi::ObjectWrap<ClassExample>::Unwrap(object_parent);
+    ActualClass* parent_actual_class_instance = example_parent->GetInternalInstance();
+    this->actualClass_ = new ActualClass(parent_actual_class_instance->getValue());
+    return;
   }
 
   Napi::Number value = info[0].As<Napi::Number>();
@@ -51,4 +60,8 @@ Napi::Value ClassExample::Add(const Napi::CallbackInfo& info) {
   double answer = this->actualClass_->add(toAdd.DoubleValue());
 
   return Napi::Number::New(info.Env(), answer);
+}
+
+ActualClass* ClassExample::GetInternalInstance() {
+  return this->actualClass_;
 }




diff --git a/cppsrc/Samples/classexample.h b/cppsrc/Samples/classexample.h
index 1f0cf69..7f6237f 100644
--- a/cppsrc/Samples/classexample.h
+++ b/cppsrc/Samples/classexample.h
@@ -5,6 +5,7 @@ class ClassExample : public Napi::ObjectWrap<ClassExample> {
  public:
   static Napi::Object Init(Napi::Env env, Napi::Object exports);
   ClassExample(const Napi::CallbackInfo& info);
+  ActualClass* GetInternalInstance();
 
  private:
   static Napi::FunctionReference constructor;
   
   
   
diff --git a/index.js b/index.js
index d849e0e..efce991 100644
--- a/index.js
+++ b/index.js
@@ -3,8 +3,13 @@ console.log('addon',testAddon);
 console.log('hello ', testAddon.hello());
 console.log('add ', testAddon.add(5, 10));
 
+const prevInstance = new testAddon.ClassExample(4.3);
+console.log('Initial value : ', prevInstance.getValue());
+console.log('After adding 3.3 : ', prevInstance.add(3.3));
+
+const newFromExisting = new testAddon.ClassExample(prevInstance);
+
+console.log('Testing class initial value for derived instance');
+console.log(newFromExisting.getValue());
 
-const classInstance = new testAddon.ClassExample(4.3);
-console.log('Testing class initial value : ',classInstance.getValue());
-console.log('After adding 3.3 : ',classInstance.add(3.3));
 module.exports = testAddon;

In the above changes.

  1. First thing we did is change the implementation of ClassExample::ClassExample so that it can take an argument which is not a number.

  2. Now we assume that if the argument is not a number, it must be an instance of the ClassExample itself. So to get the class instance from the JS side we need to UnWrap the object.

Napi::Object object_parent = info[0].As<Napi::Object>();
ClassExample* example_parent = Napi::ObjectWrap<ClassExample>::Unwrap(object_parent);
ActualClass* parent_actual_class_instance = example_parent->GetInternalInstance();
this->actualClass_ = new ActualClass(parent_actual_class_instance->getValue());
return;

So we Unwrap the object using the unwrap method and then to get to the actualClass instance of in the ClassExample we defined an additional method called GetInternalInstance which simply returns the internal actualClass reference. Finally, we take the value from actualClass instance and create new actualClass instance for the new ClassExample instance.

Lets again run it! npm run build and then node index.js

Output:

node index.js
Initial value :  4.3
After adding 3.3 :  7.6
Testing class initial value for derived instance
7.6

!! We got the expected 7.6 Wohoo !!

The entire source code is available at github

I hope this helps someone trying to use N-API and create C++/C addons for NodeJS.

Thank for reading!

How to Write Python C Extension Modules using the Python API

How to Write Python C Extension Modules using the Python API

There are several ways in which you can extend the functionality of Python. One of these is to write your Python module in C or C++. In this tutorial, you’ll discover how to use the Python API to write Python C extension modules.

You’ll learn how to:

  • Invoke C functions from within Python
  • Pass arguments from Python to C and parse them accordingly
  • Raise exceptions from C code and create custom Python exceptions in C
  • Define global constants in C and make them accessible in Python
  • Test, package, and distribute your Python C extension module

Table of Contents

  • Extending Your Python Program
  • Writing a Python Interface in C
    • Understanding fputs()
    • Writing the C Function for fputs()
    • Wrapping fputs()
    • Writing the Init Function
    • Putting It All Together
  • Packaging Your Python C Extension Module
    • Building Your Module
    • Running Your Module
  • Raising Exceptions
    • Raising Exceptions From C Code
    • Raising Custom Exceptions
  • Defining Constants
  • Testing Your Module
  • Considering Alternatives
  • Conclusion
Extending Your Python Program

One of the lesser-known yet incredibly powerful features of Python is its ability to call functions and libraries defined in compiled languages such as C or C++. This allows you to extend the capabilities of your program beyond what Python’s built-in features have to offer.

There are many languages you could choose from to extend the functionality of Python. So, why should you use C? Here are a few reasons why you might decide to build a Python C extension module:

  1. To implement new built-in object types: It’s possible to write a Python class in C, and then instantiate and extend that class from Python itself. There can be many reasons for doing this, but more often than not, performance is primarily what drives developers to turn to C. Such a situation is rare, but it’s good to know the extent to which Python can be extended.

  2. To call C library functions and system calls: Many programming languages provide interfaces to the most commonly used system calls. Still, there may be other lesser-used system calls that are only accessible through C. The os module in Python is one example.

This is not an exhaustive list, but it gives you the gist of what can be done when extending Python using C or any other language.

To write Python modules in C, you’ll need to use the Python API, which defines the various functions, macros, and variables that allow the Python interpreter to call your C code. All of these tools and more are collectively bundled in the Python.h header file.

Writing a Python Interface in C

In this tutorial, you’ll write a small wrapper for a C library function, which you’ll then invoke from within Python. Implementing a wrapper yourself will give you a better idea about when and how to use C to extend your Python module.

Understanding fputs()

fputs() is the C library function that you’ll be wrapping:

int fputs(const char *, FILE *)

This function takes two arguments:

  1. const char * is an array of characters.
  2. FILE * is a file stream pointer.

fputs() writes the character array to the file specified by the file stream and returns a non-negative value. If the operation is successful, then this value will denote the number of bytes written to the file. If there’s an error, then it returns EOF. You can read more about this C library function and its other variants in the manual page entry.

Writing the C Function for fputs()

This is a basic C program that uses fputs() to write a string to a file stream:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    FILE *fp = fopen("write.txt", "w");
    fputs("Real Python!", fp);
    fclose(fp);
    return 1;
}

This snippet of code can be summarized as follows:

  1. Open the file write.txt.
  2. Write the string "Real Python!" to the file.

Note: The C code in this article should build on most systems. It has been tested on GCC without using any special flags.

In the following section, you’ll write a wrapper for this C function.

Wrapping fputs()

It might seem a little weird to see the full code before an explanation of how it works. However, taking a moment to inspect the final product will supplement your understanding in the following sections. The code block below shows the final wrapped version of your C code:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &filename)) {

        return NULL;

    }


    FILE *fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

This code snippet references three object structures:

  1. PyObject
  2. PyArg_ParseTuple()
  3. PyLong_FromLong()

These are used for data type definition for the Python language. You’ll go through each of them now.

PyObject

PyObject is an object structure that you use to define object types for Python. All Python objects share a small number of fields that are defined using the PyObject structure. All other object types are extensions of this type.

PyObject tells the Python interpreter to treat a pointer to an object as an object. For instance, setting the return type of the above function as PyObject defines the common fields that are required by the Python interpreter in order to recognize this as a valid Python type.

Take another look at the first few lines of your C code:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Snip */

In line 2, you declare the argument types you wish to receive from your Python code:

  1. char *str is the string you want to write to the file stream.
  2. char *filename is the name of the file to write to.

PyArg_ParseTuple()

PyArg_ParseTuple() parses the arguments you’ll receive from your Python program into local variables:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &filename)) {

        return NULL;

    }


    /* Snip */

If you look at line 6, then you’ll see that PyArg_ParseTuple() takes the following arguments:

  • args are of type PyObject.

  • "ss" is the format specifier that specifies the data type of the arguments to parse. (You can check out the official documentation for a complete reference.)

  • &str and &filename are pointers to local variables to which the parsed values will be assigned.

PyArg_ParseTuple() evaluates to false on failure. If it fails, then the function will return NULL and not proceed any further.

fputs()

As you’ve seen before, fputs() takes two arguments, one of which is the FILE * object. Since you can’t parse a Python textIOwrapper object using the Python API in C, you’ll have to use a workaround:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &filename)) {

        return NULL;

    }


    FILE *fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

Here’s a breakdown of what this code does:

  • In line 10, you’re passing the name of the file that you’ll use to create a FILE * object and pass it on to the function.
  • In line 11, you call fputs() with the following arguments:
    • str is the string you want to write to the file.
    • fp is the FILE * object you defined in line 10.

You then store the return value of fputs() in bytes_copied. This integer variable will be returned to the fputs() invocation within the Python interpreter.

PyLong_FromLong(bytes_copied)

PyLong_FromLong() returns a PyLongObject, which represents an integer object in Python. You can find it at the very end of your C code:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &filename)) {

        return NULL;

    }


    FILE *fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

Line 14 generates a PyLongObject for bytes_copied, the variable to be returned when the function is invoked in Python. You must return a PyObject* from your Python C extension module back to the Python interpreter.

Writing the Init Function

You’ve written the code that makes up the core functionality of your Python C extension module. However, there are still a few extra functions that are necessary to get your module up and running. You’ll need to write definitions of your module and the methods it contains, like so:

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};

These functions include meta information about your module that will be used by the Python interpreter. Let’s go through each of the structs above to see how they work.

PyMethodDef

In order to call the methods defined in your module, you’ll need to tell the Python interpreter about them first. To do this, you can use PyMethodDef. This is a structure with 4 members representing a single method in your module.

Ideally, there will be more than one method in your Python C extension module that you want to be callable from the Python interpreter. This is why you need to define an array of PyMethodDef structs:

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};

Each individual member of the struct holds the following info:

  • "fputs" is the name the user would write to invoke this particular function.

  • method_fputs is the name of the C function to invoke.

  • METH_VARARGS is a flag that tells the interpreter that the function will accept two arguments of type PyObject*:

    1. self is the module object.
    2. args is a tuple containing the actual arguments to your function. As explained previously, these arguments are unpacked using PyArg_ParseTuple().
  • The final string is a value to represent the method docstring.

PyModuleDef

Just as PyMethodDef holds information about the methods in your Python C extension module, the PyModuleDef struct holds information about your module itself. It is not an array of structures, but rather a single structure that’s used for module definition:

static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};

There are a total of 9 members in this struct, but not all of them are required. In the code block above, you initialize the following five:

  1. PyModuleDef_HEAD_INIT is a member of type PyModuleDef_Base, which is advised to have just this one value.

  2. "fputs" is the name of your Python C extension module.

  3. The string is the value that represents your module docstring. You can use NULL to have no docstring, or you can specify a docstring by passing a const char * as shown in the snippet above. It is of type Py_ssize_t. You can also use PyDoc_STRVAR() to define a docstring for your module.

  4. -1 is the amount of memory needed to store your program state. It’s helpful when your module is used in multiple sub-interpreters, and it can have the following values:

    • A negative value indicates that this module doesn’t have support for sub-interpreters.
    • A non-negative value enables the re-initialization of your module. It also specifies the memory requirement of your module to be allocated on each sub-interpreter session.
  5. FputsMethods is the reference to your method table. This is the array of PyMethodDef structs you defined earlier.

For more information, check out the official Python documentation on PyModuleDef.

PyMODINIT_FUNC

Now that you’ve defined your Python C extension module and method structures, it’s time to put them to use. When a Python program imports your module for the first time, it will call PyInit_fputs():

PyMODINIT_FUNC PyInit_fputs(void) {
    return PyModule_Create(&fputsmodule);
}

PyMODINIT_FUNC does 3 things implicitly when stated as the function return type:

  1. It implicitly sets the return type of the function as PyObject*.
  2. It declares any special linkages.
  3. It declares the function as extern “C.” In case you’re using C++, it tells the C++ compiler not to do name-mangling on the symbols.

PyModule_Create() will return a new module object of type PyObject *. For the argument, you’ll pass the address of the method structure that you’ve already defined previously, fputsmodule.

Note: In Python 3, your init function must return a PyObject * type. However, if you’re using Python 2, then PyMODINIT_FUNC declares the function return type as void.

Putting It All Together

Now that you’ve written the necessary parts of your Python C extension module, let’s take a step back to see how it all fits together. The following diagram shows the components of your module and how they interact with the Python interpreter:

Python C API Communication

When you import your Python C extension module, PyInit_fputs() is the first method to be invoked. However, before a reference is returned to the Python interpreter, the function makes a subsequent call to PyModule_Create(). This will initialize the structures PyModuleDef and PyMethodDef, which hold meta information about your module. It makes sense to have them ready since you’ll make use of them in your init function.

Once this is complete, a reference to the module object is finally returned to the Python interpreter. The following diagram shows the internal flow of your module:

Python C API Module API

The module object returned by PyModule_Create() has a reference to the module structure PyModuleDef, which in turn has a reference to the method table PyMethodDef. When you call a method defined in your Python C extension module, the Python interpreter uses the module object and all of the references it carries to execute the specific method. (While this isn’t exactly how the Python interpreter handles things under the hood, it’ll give you an idea of how it works.)

Similarly, you can access various other methods and properties of your module, such as the module docstring or the method docstring. These are defined inside their respective structures.

Now you have an idea of what happens when you call fputs() from the Python interpreter. The interpreter uses your module object as well as the module and method references to invoke the method. Finally, let’s take a look at how the interpreter handles the actual execution of your Python C extension module:

Python C API fputs Function Flow

Once method_fputs() is invoked, the program executes the following steps:

  1. Parse the arguments you passed from the Python interpreter with PyArg_ParseTuple()
  2. Pass these arguments to fputs(), the C library function that forms the crux of your module
  3. Use PyLong_FromLong to return the value from fputs()

To see these same steps in code, take a look at method_fputs() again:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &filename)) {

        return NULL;

    }


    FILE *fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

To recap, your method will parse the arguments passed to your module, send them on to fputs(), and return the results.

Packaging Your Python C Extension Module

Before you can import your new module, you first need to build it. You can do this by using the Python package distutils.

You’ll need a file called setup.py to install your application. For this tutorial, you’ll be focusing on the part specific to the Python C extension module.

A minimal setup.py file for your module should look like this:

from distutils.core import setup, Extension

def main():
    setup(name="fputs",
          version="1.0.0",
          description="Python interface for the fputs C library function",
          author="<your name>",
          author_email="[email protected]",
          ext_modules=[Extension("fputs", ["fputsmodule.c"])])

if __name__ == "__main__":
    main()

The code block above shows the standard arguments that are passed to setup(). Take a closer look at the last positional argument, ext_modules. This takes a list of objects of the Extensions class. An object of the Extensions class describes a single C or C++ extension module in a setup script. Here, you pass two keyword arguments to its constructor, namely:

  • name is the name of the module.
  • [filename] is a list of paths to files with the source code, relative to the setup script.
[Remove ads](/account/join/)

Building Your Module

Now that you have your setup.py file, you can use it to build your Python C extension module. It’s strongly advised that you use a virtual environment to avoid conflicts with your Python environment.

Navigate to the directory containing setup.py and run the following command:

$ python3 setup.py install

This command will compile and install your Python C extension module in the current directory. If there are any errors or warnings, then your program will throw them now. Make sure you fix these before you try to import your module.

By default, the Python interpreter uses clang for compiling the C code. If you want to use gcc or any other C compiler for the job, then you need to set the CC environment variable accordingly, either inside the setup script or directly on the command line. For instance, you can tell the Python interpreter to use gcc to compile and build your module this way:

$ CC=gcc python3 setup.py install

However, the Python interpreter will automatically fall back to gcc if clang is not available.

Running Your Module

Now that everything is in place, it’s time to see your module in action! Once it’s successfully built, fire up the interpreter to test run your Python C extension module:

>>> import fputs
>>> fputs.__doc__
'Python interface for the fputs C library function'
>>> fputs.__name__
'fputs'
>>> # Write to an empty file named `write.txt`
>>> fputs.fputs("Real Python!", "write.txt")
13
>>> with open("write.txt", "r") as f:
>>>     print(f.read())
'Real Python!'

Your function performs as expected! You pass a string "Real Python!" and a file to write this string to, write.txt. The call to fputs() returns the number of bytes written to the file. You can verify this by printing the contents of the file.

Also recall how you passed certain arguments to the PyModuleDef and PyMethodDef structures. You can see from this output that Python has used these structures to assign things like the function name and docstring.

With that, you have a basic version of your module ready, but there’s a lot more that you can do! You can improve your module by adding things like custom exceptions and constants.

Raising Exceptions

Python exceptions are very different from C++ exceptions. If you want to raise Python exceptions from your C extension module, then you can use the Python API to do so. Some of the functions provided by the Python API for exception raising are as follows:

 How to Write Python C Extension Modules using the Python API

You can use any of these to raise an exception. However, which to use and when depends entirely on your requirements. The Python API has all the standard exceptions pre-defined as PyObject types.

Raising Exceptions From C Code

While you can’t raise exceptions in C, the Python API will allow you to raise exceptions from your Python C extension module. Let’s test this functionality by adding PyErr_SetString() to your code. This will raise an exception whenever the length of the string to be written is less than 10 characters:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &fd)) {

        return NULL;

    }


    if (strlen(str) < 10) {

        PyErr_SetString(PyExc_ValueError, "String length must be greater than 10");

        return NULL;

    }


    fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

Here, you check the length of the input string immediately after you parse the arguments and before you call fputs(). If the string passed by the user is shorter than 10 characters, then your program will raise a ValueError with a custom message. The program execution stops as soon as the exception occurs.

Note how method_fputs() returns NULL after raising the exception. This is because whenever you raise an exception using PyErr_*(), it automatically sets an internal entry in the exception table and returns it. The calling function is not required to subsequently set the entry again. For this reason, the calling function returns a value that indicates failure, usually NULL or -1. (This should also explain why there was a need to return NULL when you parse arguments in method_fputs() using PyArg_ParseTuple().)

Raising Custom Exceptions

You can also raise custom exceptions in your Python C extension module. However, things are a bit different. Previously, in PyMODINIT_FUNC, you were simply returning the instance returned by PyModule_Create and calling it a day. But for your custom exception to be accessible by the user of your module, you need to add your custom exception to your module instance before you return it:

static PyObject *StringTooShortError = NULL;

PyMODINIT_FUNC PyInit_fputs(void) {
    /* Assign module value */
    PyObject *module = PyModule_Create(&fputsmodule);

    /* Initialize new exception object */
    StringTooShortError = PyErr_NewException("fputs.StringTooShortError", NULL, NULL);

    /* Add exception object to your module */
    PyModule_AddObject(module, "StringTooShortError", StringTooShortError);

    return module;
}

As before, you start off by creating a module object. Then you create a new exception object using PyErr_NewException. This takes a string of the form module.classname as the name of the exception class that you wish to create. Choose something descriptive to make it easier for the user to interpret what has actually gone wrong.

Next, you add this to your module object using PyModule_AddObject. This takes your module object, the name of the new object being added, and the custom exception object itself as arguments. Finally, you return your module object.

Now that you’ve defined a custom exception for your module to raise, you need to update method_fputs() so that it raises the appropriate exception:

static PyObject *method_fputs(PyObject *self, PyObject *args) {

    char *str, *filename = NULL;

    int bytes_copied = -1;


    /* Parse arguments */

    if(!PyArg_ParseTuple(args, "ss", &str, &fd)) {

        return NULL;

    }


    if (strlen(str) < 10) {

        /* Passing custom exception */

        PyErr_SetString(StringTooShortError, "String length must be greater than 10");

        return NULL;

    }


    fp = fopen(filename, "w");

    bytes_copied = fputs(str, fp);

    fclose(fp);


    return PyLong_FromLong(bytes_copied);

}

After building the module with the new changes, you can test that your custom exception is working as expected by trying to write a string that is less than 10 characters in length:

>>> import fputs
>>> # Custom exception
>>> fputs.fputs("RP!", fp.fileno())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
fputs.StringTooShortError: String length must be greater than 10

When you try to write a string with fewer than 10 characters, your custom exception is raised with a message explaining what went wrong.

Defining Constants

There are cases where you’ll want to use or define constants in your Python C extension module. This is quite similar to how you defined custom exceptions in the previous section. You can define a new constant and add it to your module instance using PyModule_AddIntConstant():

PyMODINIT_FUNC PyInit_fputs(void) {
    /* Assign module value */
    PyObject *module = PyModule_Create(&fputsmodule);

    /* Add int constant by name */
    PyModule_AddIntConstant(module, "FPUTS_FLAG", 64);

    /* Define int macro */
    #define FPUTS_MACRO 256

    /* Add macro to module */
    PyModule_AddIntMacro(module, FPUTS_MACRO);

    return module;
}

This Python API function takes the following arguments:

  • The instance of your module
  • The name of the constant
  • The value of the constant

You can do the same for macros using PyModule_AddIntMacro():

PyMODINIT_FUNC PyInit_fputs(void) {
    /* Assign module value */
    PyObject *module = PyModule_Create(&fputsmodule);

    /* Add int constant by name */
    PyModule_AddIntConstant(module, "FPUTS_FLAG", 64);

    /* Define int macro */
    #define FPUTS_MACRO 256

    /* Add macro to module */
    PyModule_AddIntMacro(module, FPUTS_MACRO);

    return module;
}

This function takes the following arguments:

  • The instance of your module
  • The name of the macro that has already been defined

Note: If you want to add string constants or macros to your module, then you can use PyModule_AddStringConstant() and PyModule_AddStringMacro(), respectively.

Open up the Python interpreter to see if your constants and macros are working as expected:

>>> import fputs
>>> # Constants
>>> fputs.FPUTS_FLAG
64
>>> fputs.FPUTS_MACRO
256

Here, you can see that the constants are accessible from within the Python interpreter.

[Remove ads](/account/join/)
Testing Your Module

You can test your Python C extension module just as you would any other Python module. This can be demonstrated by writing a small test function for pytest:

import fputs

def test_copy_data():
    content_to_copy = "Real Python!"
    bytes_copied = fputs.fputs(content_to_copy, 'test_write.txt')

    with open('test_write.txt', 'r') as f:
        content_copied = f.read()

    assert content_copied == content_to_copy

In the test script above, you use fputs.fputs() to write the string "Real Python!" to an empty file named test_write.txt. Then, you read in the contents of this file and use an assert statement to compare it to what you had originally written.

You can run this test suite to make sure your module is working as expected:

$ pytest -q
test_fputs.py                                                 [100%]
1 passed in 0.03 seconds
Considering Alternatives

In this tutorial, you’ve built an interface for a C library function to understand how to write Python C extension modules. However, there are times when all you need to do is invoke some system calls or a few C library functions, and you want to avoid the overhead of writing two different languages. In these cases, you can use Python libraries such as ctypes or cffi.

These are Foreign Function libraries for Python that provide access to C library functions and data types. Though the community itself is divided as to which library is best, both have their benefits and drawbacks. In other words, either would make a good choice for any given project, but there are a few things to keep in mind when you need to decide between the two:

  • The ctypes library comes included in the Python standard library. This is very important if you want to avoid external dependencies. It allows you to write wrappers for other languages in Python.

  • The cffi library is not yet included in the standard library. This might be a dealbreaker for your particular project. In general, it’s more Pythonic in nature, but it doesn’t handle preprocessing for you.

For more information on these libraries, check out Extending Python With C Libraries and the “ctypes” Module and Interfacing Python and C: The CFFI Module.

Note: Apart from ctypes and cffi, there are various other tools available. For instance, you can also use swig and boost::Py.

Conclusion

In this tutorial, you’ve learned how to write a Python interface in the C programming language using the Python API. You wrote a Python wrapper for the fputs() C library function. You also added custom exceptions and constants to your module before building and testing it.

The Python API provides a host of features for writing complex Python interfaces in the C programming language. At the same time, libraries such as cffi or ctypes can lower the amount of overhead involved in writing Python C extension modules. Make sure you weigh all the factors before making a decision!

A guide to Object Detection with OpenCV and Swift

A guide to Object Detection with OpenCV and Swift

In this article, we’ll see how to create and launch a object detection algorithm using OpenCV and Swift

Swift has been with us for a while now, and through its iterations, it has brought to us all the features of a modern object-oriented programming language. These include optionals, generics, tuples, structs that support methods, extensions and protocols, and many more. But if your application relies on a library that’s written using C++ then you can’t count on Swift anymore. Luckily Objective-C++ is here to help us.

Since its introduction, Swift has had great interoperability with Objective-C and we will use Objective-C for bridging Swift with C++. Objective-C++ is nothing more than Objective-C with the ability to link with C++ code, and using that, in this blog post, we will create a simple app that will recognize the Toptal logo inside the image using OpenCV. When we detect that logo, we’ll open the Toptal home page.

As stated on the OpenCV web page:

"OpenCV was designed for computational efficiency and with a strong focus on real-time applications. Written in optimized C/C++, the library can take advantage of multi-core processing."
This is a great solution if you want fast to develop and reliable computer vision.

Creating the OpenCV Objective-C++ Wrapper

In this tutorial, we will design the application which will match a Toptal logo inside an image and open Toptal web page. To begin, create a new Xcode project and set up CocoaPods using pod init. Add OpenCV to Podfile pod 'OpenCV and run pod install in Terminal. Be sure to uncomment use_frameworks! statement inside Podfile.

Now, when we have OpenCV inside Xcode project, we have to connect it with Swift. Here is a quick outline of the steps involved:

Step 1: Create a new Objective-C class OpenCVWrapper. When Xcode asks you “Would you like to configure an Objective-C bridging header?” choose “Create bridging header.” The bridging header is the place where you import Objective-C classes, and then they are visible inside Swift.

Step 2: In order to use C++ inside Objective-C, we have to change the file extension from OpenCVWrapper.m to OpenCVWrapper.mm. You can do it by simply renaming the file inside Xcode’s project navigator. Adding .mm as an extension will change the file type from Objective-C to Objective-C++.

Step 3: Import OpenCV into OpenCVWrapper.mm using the following import. It’s important to write the given import above #import "OpenCVWrapper.h" because this way we avoid a well-known BOOL conflict. OpenCV contains enum that has the value NO which causes a conflict with the Objective-C BOOL NO value. If you don’t need classes that use such enum, then this is the simplest way. Otherwise, you have to undefine BOOL before importing OpenCV.

#ifdef __cplusplus 
 
#import <opencv2/opencv.hpp> 
 
#import <opencv2/imgcodecs/ios.h> 
 
#import <opencv2/videoio/cap_ios.h> 
 
#endif

Step 4: Add #import "OpenCVWrapper.h" to your bridging header.

Open OpenCVWrapper.mm and create a private interface where we will declare private properties:

@interface OpenCVWrapper() <CvVideoCameraDelegate>
 
@property (strong, nonatomic) CvVideoCamera *videoCamera;
 
@property (assign, nonatomic) cv::Mat logoSample;
 
@end

In order to create CvVideoCamera, we have to pass UIImageView to it, and we will do that through our designator initializer.

- (instancetype)initWithParentView:(UIImageView *)parentView delegate:(id<OpenCVWrapperDelegate>)delegate {
 
   
 
    if (self = [super init]) {
 
        self.delegate = delegate;
 
       
 
        parentView.contentMode = UIViewContentModeScaleAspectFill;
 
       
 
        self.videoCamera = [[CvVideoCamera alloc] initWithParentView:parentView];
 
        self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack;
 
        self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetHigh;
 
        self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
 
        self.videoCamera.defaultFPS = 30;
 
        self.videoCamera.grayscaleMode = [NSNumber numberWithInt:0].boolValue;
 
        self.videoCamera.delegate = self;
 
       
 
        // Convert UIImage to Mat and store greyscale version
 
        UIImage *templateImage = [UIImage imageNamed:@"toptal"];
 
        cv::Mat templateMat;
 
        UIImageToMat(templateImage, templateMat);
 
        cv::Mat grayscaleMat;
 
        cv::cvtColor(templateMat, grayscaleMat, CV_RGB2GRAY);
 
        self.logoSample = grayscaleMat;
 
       
 
        [self.videoCamera start];
 
    }
 
    return self;
 
}

Inside it, we configure CvVideoCamera that renders video inside the given parentView and through delegate sends us cv::Mat image for analysis.

processImage: method is from CvVideoCameraDelegate protocol, and inside it, we will do template matching.

- (void)processImage:(cv::Mat&)image {
 
   
 
    cv::Mat gimg;
 
   
 
    // Convert incoming img to greyscale to match template
 
    cv::cvtColor(image, gimg, CV_BGR2GRAY);
 
   
 
    // Get matching
 
    cv::Mat res(image.rows-self.logoSample.rows+1, self.logoSample.cols-self.logoSample.cols+1, CV_32FC1);
 
    cv::matchTemplate(gimg, self.logoSample, res, CV_TM_CCOEFF_NORMED);
 
    cv::threshold(res, res, 0.5, 1., CV_THRESH_TOZERO);
 
   
 
    double minval, maxval, threshold = 0.9;
 
    cv::Point minloc, maxloc;
 
    cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);
 
   
 
    // Call delegate if match is good enough
 
    if (maxval >= threshold)
 
    {
 
        // Draw a rectangle for confirmation
 
        cv::rectangle(image, maxloc, cv::Point(maxloc.x + self.logoSample.cols, maxloc.y + self.logoSample.rows), CV_RGB(0,255,0), 2);
 
        cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.));
 
       
 
        [self.delegate openCVWrapperDidMatchImage:self];
 
    }
 
}

First, we convert the given image to grayscale image because inside the init method we converted our Toptal logo template matching image to grayscale. Next step is to check for matches with a certain threshold which will help us with scaling and angles. We have to check for angles because you can capture a photo in various angles in which we still want to detect logo. After reaching the given threshold we will invoke delegate and open Toptal’s web page.

Don’t forget to add NSCameraUsageDescription to your Info.plist otherwise, your application will crash right after calling [self.videoCamera start];.

Now Finally Swift

So far we were focusing on Objective-C++ because all the logic is done inside it. Our Swift code will be fairly simple:

  1. Inside ViewController.swift, create UIImageView where CvVideoCamera will render content.
  2. Create an instance of OpenCVWrapper and pass the UIImageView instance to it.
  3. Implement OpenCVWrapperDelegate protocol to open Toptal’s web page when we detect the logo.
class ViewController: UIViewController {
 
   
 
    var wrapper: OpenCVWrapper!
 
   
 
    @IBOutlet var imageView: UIImageView!
 
    override func viewDidLoad() {
 
        super.viewDidLoad()
 
        // Do any additional setup after loading the view, typically from a nib.
 
   
 
        wrapper = OpenCVWrapper.init(parentView: imageView, delegate: self)
 
    }
 
}
 
extension ViewController: OpenCVWrapperDelegate {
 
    //MARK: - OpenCVWrapperDelegate
 
   
 
    func openCVWrapperDidMatchImage(_ wrapper: OpenCVWrapper) {
 
        UIApplication.shared.open(URL.init(string: "https://toptal.com")!, options: [:], completionHandler: nil)
 
    }
 
}

OpenCV Swift in Action

In this article, we have shown how you can integrate C++ code with Swift and create wrapper classes that are here for bridging C++ code with Swift. Now, when we detect the Toptal Logo through the camera, we open Toptal’s home page.

For future updates, you may want to run CV template matching in a background thread. This way, you won’t block the main thread and the UI will stay responsive. Because this is a simple example of OpenCV, template matching may not be extra successful, but the purpose of this article was to show you how you can start using it.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading about OpenCV and Python

Complete Python Bootcamp: Go from zero to hero in Python 3

Machine Learning A-Z™: Hands-On Python & R In Data Science

Python and Django Full Stack Web Developer Bootcamp

Computer Vision Using OpenCV

OpenCV Python Tutorial - Computer Vision With OpenCV In Python

Python Tutorial: Image processing with Python (Using OpenCV)

A guide to Face Detection in Python

Machine Learning Tutorial - Image Processing using Python, OpenCV, Keras and TensorFlow

Face Detection using Open-CV

C++ Tutorial from Basic to Advance

C++ Tutorial from Basic to Advance

Learn C++ from beginner level to advanced level