I am trying to call C++ functions from a dll using ctypes in python. My current issue is the function seems to return a large int, either positive or negative, instead of the char pointer I expect it to. If I convert that int to a c_char_p and call .value on it, it kills my kernel every single time. I've looked all over this site and in the docs too and can't figure this out. A lot of the things I have seen on this site even throw errors for me, like passing in strings to ctypes opjects and functions when they should be byte objects or something similar. Below is my c++ code that is turned into a dll and the python code I am using to call functions from the dll. Please if anyone can help me, that would be awesome. SaySomething is the function in question. Thanks.
#pragma once
#ifdef TESTLIBRARY_EXPORTS
#define TESTLIBRARY_API __declspec(dllexport)
#else
#define TESTLIBRARY_API __declspec(dllexport)
#endif
#include <windows.h>
#include <cstring>
#ifdef __cplusplus
extern "C"
{
#endif
TESTLIBRARY_API char* SaySomething(const char* phrase);
#ifdef __cplusplus
};
#endif
#include "stdafx.h"
#include "TestLibrary.h"
#include <iostream>
TESTLIBRARY_API char* SaySomething(const char* phrase)
{
char* p = new char [100];
p = "string something";
return p;
}
import ctypes
dbl = ctypes.c_double
pChar = ctypes.c_char_p
pVoid = ctypes.c_void_p
libName = (r"D:\Documents\Coding Stuff\Visual Studio 2017\Projects\TestLibrary"
r"Solution\x64\Debug\TestLibrary.dll")
x = ctypes.windll.LoadLibrary(libName)
x.SaySomething.argtypes = [pChar]
x.SaySomething.restypes = pChar
phrase = b"Hi"
phrase = pChar(phrase)
res = x.SaySomething(phrase)
While you can make an API that does what you are trying to do, you currently will have a memory leak. A better solution is to have Python allocate and manage the memory for the result.
I also fixed the dllimport
as mentioned in the comments and defined TESTLIBRARY_EXPORTS
in the .cpp file so the function would export from the DLL. restype
was also fixed.
TesterLibrary.h
#pragma once
#ifdef TESTLIBRARY_EXPORTS
#define TESTLIBRARY_API __declspec(dllexport)
#else
#define TESTLIBRARY_API __declspec(dllimport)
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
TESTLIBRARY_API char* SaySomething(const char* phrase, char* result, size_t resultMaxLength);
#ifdef __cplusplus
}
#endif
TesterLibrary.cpp
#define TESTLIBRARY_EXPORTS
#include "TestLibrary.h"
#include <stdio.h>
TESTLIBRARY_API char* SaySomething(const char* phrase, char* result, size_t resultMaxLength)
{
_snprintf_s(result,resultMaxLength,_TRUNCATE,"Decorated <%s>",phrase);
return result;
}
tester2.py
import ctypes
libName = (r"TestLibrary.dll")
x = ctypes.CDLL(libName)
x.SaySomething.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.c_size_t]
x.SaySomething.restype = ctypes.c_char_p
phrase = b"Hi"
result = ctypes.create_string_buffer(100)
res = x.SaySomething(phrase,result,ctypes.sizeof(result))
print(res)
print(result.value)
Output
b'Decorated <Hi>'
b'Decorated <Hi>'
Python will automatically free the result
buffer when there are no more references to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With