Friday, 23 June 2017

Call a dll from Python

Letting VS2015 make a dll called SomeDLL for me with these implementations

// SomeDll.cpp : 
// Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "SomeDll.h"


// This is an example of an exported variable
SOMEDLL_API int nSomeDll=0;

// This is an example of an exported function.
SOMEDLL_API int fnSomeDll(void)
{
    return 42;
}

// This is the constructor of a class that has been exported.
// see SomeDll.h for the class definition
CSomeDll::CSomeDll()
{
    return;
}
 

I then make a python script, using ctypes and loading the dll, using os to find it:

import os
import ctypes

os.chdir("C:\\Users\\sbkg525\\src\\SomeDll\\Debug")
SomeDll = ctypes.WinDLL("SomeDll.dll")


I can either use attributes of the library or use protoypes. I tried protoypes first.The function returns an int and takes no parameters:

proto = ctypes.WINFUNCTYPE(ctypes.c_int)
params = ()

answer = proto(("fnSomeDll", SomeDll), params)


Unfortunately this says

AttributeError: function 'fnSomeDll' not found

because C++ is name mangled. extern "C" FTW another time; for now

link.exe /dump /exports Debug\SomeDll.dll

          1    0 0001114F ??0CSomeDll@@QAE@XZ =

                  @ILT+330(??0CSomeDll@@QAE@XZ)
          2    1 00011244 ??4CSomeDll@@QAEAAV0@$$QAV0@@Z =

                  @ILT+575(??4CSomeDll@@QAEAAV0@$$QAV0@@Z)
          3    2 0001100A ??4CSomeDll@@QAEAAV0@ABV0@@Z =

                  @ILT+5(??4CSomeDll@@QAEAAV0@ABV0@@Z)
          4    3 0001111D ?fnSomeDll@@YAHXZ =

                  @ILT+280(?fnSomeDll@@YAHXZ)
          5    4 00018138 ?nSomeDll@@3HA =

                  ?nSomeDll@@3HA (int nSomeDll)

Looks like we want 4;

answer = proto(("?fnSomeDll@@YAHXZ", SomeDll), params)

print answer

>>> <WinFunctionType object at 0x0248A7B0>


Of course. It's a function. Let's call the function

print answer()
>>> 42


Done. I'll try attributes next. And functions which take parameters. Later, I'll look at other calling conventions.

First, the docs says, "foreign functions can be accessed as attributes of loaded shared libraries.
Given

extern "C"
{
    SOMEDLL_API void hello_world()
    {
        //now way of telling this has worked
    }

}

we call it like this

lib = ctypes.cdll.LoadLibrary('SomeDll.dll')
lib.hello_world()


It seems to assume a return type of int. For example,

extern "C"
{
    SOMEDLL_API double some_number()
    {
        return 1.01;
    }

}

called as follows

lib = ctypes.cdll.LoadLibrary('SomeDll.dll')
lib.hello_world()
val = lib.some_number()
print val, type(val)

Gives

-858993460, <type 'int'>


We need to specify the return type, since it's not an int:



lib.some_number.restype = ctypes.c_double
val = lib.some_number()
print val, type(val)


then we get what we want

1.01 <type 'float'>

We need to do likewise for parameters

extern "C"
{
    SOMEDLL_API double add_numbers(double x, double y)
    {
        return x + y;
    }
}


If we just try to call it with some floats we get an error

    total = lib.add_numbers(10.5, 25.7)
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1


Stating the parameter type fixes this

lib.add_numbers.restype = ctypes.c_double
lib.add_numbers.argtypes = [ctypes.c_double, ctypes.c_double]
total = lib.add_numbers(10.5, 25.7)
print total, type(total)


36.2 <type 'float'>

Just one starter thought on strings. Returning a const char * seems to give a str in python

SOMEDLL_API const char * speak()
{
    return "Hello";


called like this



lib.speak.restype = ctypes.c_char_p
print lib.speak()


says "Hello"; using parameters as strings and particularly as refrences that can be changed needs some investigation.

Does a similar approach using attributes of the loaded library work for non-extern "C" functions? Can I use the proto approach on the extern "C" functions?

Let's see...







Codes of Conduct

There's been yet another thread about code of conducts at conferences on twitter, and I wanted to compare them to conditions of sale for gig or festival tickets. Here's an example:
Let's consider a sample:
1. I can't turn up before it starts? Why even say that? Oh, and 2. I have to leave when it's over. THIS IS PC GONE MAD. OK, not PC. But why do you need to spell this out? It's like putting a precondition of a string has to terminate with a null for you to call strlen.
3. Yeah, rulez. Whatever. Surprised you didn't say it's illegal to break the law. What is this?
Blahblahblah.
9. Yeah, fair enough. But what about flame throwers?
No, no, no...
16. Does that mean I can bring *Real* weapons?
Blahblahblah.

25. There might be swear words?! Why tell me that?

Or maybe some people will bring kids with them and that might need a sane conversation about a time and a place for certain behaviours. I know the bands, I know what kind of music to expect. I know what I'm walking in to.

I also know there's a clearly marked welfare tent on site just in case.

And wardens on the campsite wearing obvious vests.

And hundreds of programmers listening to their favourite rock stars.
(OK, not all the punters are programmers, but many are).

Why did I ever go to a field full of metallers? (Knowing I'd probably be one of the few women there). I went with friends, which made me feel safer. I wanted to listen to bands I knew, and discover new music. If I'd gone by myself, knowing in advance about wardens and the welfare tent would have made me feel OK. Hey, the conditions of sale show the organisers have thought about things that might go wrong or concern people, and that makes me feel safer.

Do they make people think, "This is PC gone mad? If you need to tell me not to set fire to myself and drink myself to death then you are insulting me and I want nothing to do with this?"

Not by the looks of the number of people who turn up. And there have been more women and kids recently which is great.

What are codes of conduct for? Quite frankly me. But not just me. They are not there to tell you how to behave because the organisers think white guys don't know how to conduct themselves, and that all such guys are potential rapists or murders. In some ways, the logic of stating a CoC is pointless because we know how to be nice taken to extreme could mean laws are pointless. Why say "You aren't allowed to commit murder?" Surely that doesn't need pointing out? And yet most countries have such a law.

Conditions of sale and code of conducts aren't laws, but they give a shared statement of expectation and make me feel OK about going to conferences/talks/festivals/gigs alone. And then I meet loads of new people and discover new music. And I can't wait til Bloodstock. Or the next tech talk/conference I go to.