{"id":125,"date":"2012-06-10T18:47:02","date_gmt":"2012-06-10T16:47:02","guid":{"rendered":"https:\/\/blogs.gentoo.org\/mgorny\/?p=125"},"modified":"2012-06-10T19:11:53","modified_gmt":"2012-06-10T17:11:53","slug":"a-c-api-for-c-and-python-ones-or-making-of-libh2o","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2012\/06\/10\/a-c-api-for-c-and-python-ones-or-making-of-libh2o\/","title":{"rendered":"A C API for C++ and Python ones \u2014 or making of libh2o"},"content":{"rendered":"<p>Lately I spent a\u00a0lot of\u00a0time working on\u00a0a\u00a0small project of\u00a0mine called libh2o. Its goal is to\u00a0provide a\u00a0library of\u00a0routines implementing <a rel='external' href='http:\/\/iapws.org\/'>IAPWS IF97<\/a> equations for\u00a0water and\u00a0steam properties. With the\u00a0core written in\u00a0C, and\u00a0providing a\u00a0nice-to-use API for\u00a0C++ and\u00a0Python.<\/p>\n<p>At\u00a0first, I thought about not providing a\u00a0\u00abhigh level\u00bb C API at\u00a0all. It was like: if you want to\u00a0use plain C, you&#8217;ve gotta glue all the\u00a0low-level equations yourself. However, after some thinking I decided to\u00a0provide one, and\u00a0built the\u00a0two remaining APIs (C++ and\u00a0Python) on top of\u00a0it.<\/p>\n<p>The\u00a0main reason for\u00a0doing this was that Python (well, CPython) is\u00a0written in\u00a0C. Although I&#8217;ve seen people writing Python extensions in\u00a0C++, and\u00a0even using some of\u00a0C++ features to\u00a0make them a\u00a0little nicer, that&#8217;s still a\u00a0bunch of\u00a0ugly C hacks and\u00a0pointer casts. I don&#8217;t see a\u00a0really good reason to\u00a0write a\u00a0Python extension in\u00a0C++, nor to\u00a0make it depend on a\u00a0C++ compiler when\u00a0it&#8217;s all limited to\u00a0C-based CPython API anyway.<\/p>\n<p>And\u00a0that means that I have either to\u00a0duplicate all the\u00a0high-level logic in\u00a0the\u00a0Python extension, or\u00a0just create a\u00a0C API first and\u00a0reuse that. Since the\u00a0whole logic was simple enough to be\u00a0covered completely and\u00a0clearly in\u00a0C, I have chosen this way.<\/p>\n<p>As it happens when people choose C, I had to implement some kind of\u00a0poor man&#8217;s objectivity. Not something as\u00a0wide (and\u00a0ugly) as\u00a0GObject (someone, <em>please<\/em> kill it!) but a\u00a0few bits necessary to\u00a0keep the\u00a0state. In\u00a0other words, a\u00a0structure keeping the\u00a0\u00abobject\u00bb and\u00a0a\u00a0bunch of\u00a0nicely named functions taking it as\u00a0their first argument.<\/p>\n<p>Before I learnt C++, I would assume that the\u00a0object structure should be a\u00a0private (and\u00a0obscured) blob, and\u00a0the\u00a0object type should be an\u00a0incomplete pointer to it. User should just grab that pointer from a\u00a0\u00abconstructor\u00bb, pass it around and\u00a0finally free it through\u00a0a\u00a0\u00abdestructor\u00bb. Advantage: the\u00a0exact struct contents are\u00a0not the\u00a0part of\u00a0ABI.<\/p>\n<p>But now I&#8217;ve decided to\u00a0go the\u00a0other way; way similar to\u00a0how C++ classes work. I&#8217;ve created a\u00a0structure with explicitly listed private fields (and\u00a0a\u00a0very simple <code>\/*private:*\/<\/code> comment), and\u00a0used that as\u00a0the\u00a0public type. It doesn&#8217;t need to keep any memory allocated, and\u00a0is simple enough to be\u00a0allocated on\u00a0stack. Advantages: no\u00a0need for\u00a0a\u00a0destructor, and\u00a0an\u00a0ability to\u00a0pack that struct in\u00a0the\u00a0C++ class which will wrap it.<\/p>\n<p>Then the\u00a0usual stuff: a\u00a0bunch of\u00a0functions with\u00a0common prefixes. One prefix for\u00a0the\u00a0\u00abnamespace\u00bb, another one for\u00a0the function (<code>new<\/code>, <code>get<\/code>\u2026). All in\u00a0nice and\u00a0clear fashion, either to be\u00a0used directly or\u00a0wrapped in\u00a0the\u00a0C++ or\u00a0Python APIs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lately I spent a\u00a0lot of\u00a0time working on\u00a0a\u00a0small project of\u00a0mine called libh2o. Its goal is to\u00a0provide a\u00a0library of\u00a0routines implementing IAPWS IF97 equations for\u00a0water and\u00a0steam properties. With the\u00a0core written in\u00a0C, and\u00a0providing a\u00a0nice-to-use API for\u00a0C++ and\u00a0Python. At\u00a0first, I thought about not providing a\u00a0\u00abhigh level\u00bb C API at\u00a0all. It was like: if you want to\u00a0use plain C, you&#8217;ve gotta &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2012\/06\/10\/a-c-api-for-c-and-python-ones-or-making-of-libh2o\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;A C API for C++ and Python ones \u2014 or making of libh2o&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[8],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/125"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=125"}],"version-history":[{"count":4,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/125\/revisions"}],"predecessor-version":[{"id":129,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/125\/revisions\/129"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=125"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=125"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=125"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}