Skip to content

Commit

Permalink
Automatically generate C++ bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
rescrv committed Mar 8, 2015
1 parent 44a288b commit b3bd466
Show file tree
Hide file tree
Showing 9 changed files with 725 additions and 191 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,7 @@ maint_lib_check_LDADD = -ldl

maintainer-generate:
python2 bindings/c.py
python2 bindings/cc.py
python2 bindings/go.py
python2 bindings/java.py
python2 bindings/nodejs.py
Expand Down
6 changes: 3 additions & 3 deletions bindings/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ def generate_admin_doc():
enum hyperdex_client_returncode* status);
int
hyperdex_client_poll(struct hyperdex_client* client);
hyperdex_client_poll_fd(struct hyperdex_client* client);
int
hyperdex_client_block(struct hyperdex_client* client, int timeout);
Expand Down Expand Up @@ -687,11 +687,11 @@ def generate_admin_doc():
}
HYPERDEX_API int
hyperdex_client_poll(hyperdex_client* _cl)
hyperdex_client_poll_fd(hyperdex_client* _cl)
{
FAKE_STATUS;
C_WRAP_EXCEPT(
return cl->poll();
return cl->poll_fd();
);
}
Expand Down
164 changes: 164 additions & 0 deletions bindings/cc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Copyright (c) 2013-2014, Cornell University
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of HyperDex nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import copy
import itertools
import os
import sys

BASE = os.path.join(os.path.dirname(__file__), '..')
sys.path.append(BASE)

import bindings
import bindings.cc

################################ Code Generation ###############################

def generate_func(x, lib, struct=None, sep='\n', namesep='_', padd=None):
assert x.form in (bindings.AsyncCall, bindings.SyncCall,
bindings.NoFailCall, bindings.Iterator)
struct = struct or lib
return_type = 'int64_t'
if x.form == bindings.SyncCall:
return_type = 'int'
if x.form == bindings.NoFailCall:
return_type = 'void'
func = ' ' + return_type + ' ' + x.name + '('
padd = ' ' * len(func) if padd is None else ' ' * padd
first = True
for arg in x.args_in:
if not first:
func += ',\n' + padd
first = False
func += ', '.join([p + ' ' + n for p, n in arg.args])
for arg in x.args_out:
if not first:
func += ',\n' + padd
first = False
func += ', '.join([p + '* ' + n for p, n in arg.args])
func += ')\n'
func = func.replace('struct ', '')
func = func.replace('enum ', '')
name = 'hyperdex_' + lib + namesep + x.name
func += ' ' * 12 + '{ return ' + name + '(m_cl'
for arg in x.args_in:
for p, n in arg.args:
func += ', ' + n
for arg in x.args_out:
for p, n in arg.args:
func += ', ' + n
func += '); }'
return func

############################### Output Generators ##############################

def generate_client_header():
fout = open(os.path.join(BASE, 'include/hyperdex/client.hpp'), 'w')
fout.write(bindings.copyright('/', '2013-2015'))
fout.write(bindings.cc.CLIENT_HEADER_HEAD)
fout.write('\n'.join([generate_func(c, 'client') for c in bindings.Client]))
fout.write(bindings.cc.CLIENT_HEADER_FOOT)

if __name__ == '__main__':
generate_client_header()

################################### Templates ##################################

CLIENT_HEADER_HEAD = '''
#ifndef hyperdex_client_hpp_
#define hyperdex_client_hpp_
// C++
#include <iostream>
// HyperDex
#include <hyperdex/client.h>
namespace hyperdex
{
class Client
{
public:
Client(const char* coordinator, uint16_t port)
: m_cl(hyperdex_client_create(coordinator, port))
{
if (!m_cl)
{
throw std::bad_alloc();
}
}
Client(const char* conn_str)
: m_cl(hyperdex_client_create_conn_str(conn_str))
{
if (!m_cl)
{
throw std::bad_alloc();
}
}
~Client() throw ()
{
hyperdex_client_destroy(m_cl);
}
public:
'''

CLIENT_HEADER_FOOT = '''
public:
void clear_auth_context()
{ return hyperdex_client_clear_auth_context(m_cl); }
void set_auth_context(const char** macaroons, size_t macaroons_sz)
{ return hyperdex_client_set_auth_context(m_cl, macaroons, macaroons_sz); }
public:
int64_t loop(int timeout, hyperdex_client_returncode* status)
{ return hyperdex_client_loop(m_cl, timeout, status); }
int poll_fd()
{ return hyperdex_client_poll_fd(m_cl); }
int block(int timeout)
{ return hyperdex_client_block(m_cl, timeout); }
std::string error_message()
{ return hyperdex_client_error_message(m_cl); }
std::string error_location()
{ return hyperdex_client_error_location(m_cl); }
private:
Client(const Client&);
Client& operator = (const Client&);
private:
hyperdex_client* m_cl;
};
} // namespace hyperdex
std::ostream&
operator << (std::ostream& lhs, hyperdex_client_returncode rhs);
#endif // hyperdex_client_hpp_
'''
2 changes: 1 addition & 1 deletion bindings/node.js/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ HyperDexClient :: HyperDexClient(const char* host, uint16_t port)
if (m_cl)
{
m_poll = new uv_poll_t;
uv_poll_init_socket(uv_default_loop(), m_poll, hyperdex_client_poll(m_cl));
uv_poll_init_socket(uv_default_loop(), m_poll, hyperdex_client_poll_fd(m_cl));
m_poll->data = this;
}

Expand Down
4 changes: 2 additions & 2 deletions client/c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1970,11 +1970,11 @@ hyperdex_client_loop(hyperdex_client* _cl, int timeout,
}

HYPERDEX_API int
hyperdex_client_poll(hyperdex_client* _cl)
hyperdex_client_poll_fd(hyperdex_client* _cl)
{
FAKE_STATUS;
C_WRAP_EXCEPT(
return cl->poll();
return cl->poll_fd();
);
}

Expand Down
2 changes: 1 addition & 1 deletion client/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ client :: loop(int timeout, hyperdex_client_returncode* status)
}

int
client :: poll()
client :: poll_fd()
{
return m_busybee.poll_fd();
}
Expand Down
2 changes: 1 addition & 1 deletion client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class client
uint64_t* update_count);
// looping/polling
int64_t loop(int timeout, hyperdex_client_returncode* status);
int poll();
int poll_fd();
int block(int timeout);
// error handling
const char* error_message();
Expand Down
2 changes: 1 addition & 1 deletion include/hyperdex/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ hyperdex_client_loop(struct hyperdex_client* client, int timeout,
enum hyperdex_client_returncode* status);

int
hyperdex_client_poll(struct hyperdex_client* client);
hyperdex_client_poll_fd(struct hyperdex_client* client);

int
hyperdex_client_block(struct hyperdex_client* client, int timeout);
Expand Down
Loading

0 comments on commit b3bd466

Please sign in to comment.