I have the following function (from windows.h) which I am trying to use the Python C API to allow python to call it. This is the function:

BOOL ReadConsoleOutputCharacter(
  HANDLE hConsoleOutput, (Type Handle to Change (use STD_OUTPUT))
  LPTSTR lpCharacter, (char pointer to store Characters read)
  DWORD nLength, (length to read)
  COORD dwReadCoord, (Type COORD to start reading at)
  LPDWORD lpNumberOfCharsRead (length actually read)

This is a function that uses it correctly:

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hOut;
    char Letters[5];
    COORD Where;
    DWORD NumRead;
    int i;

    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    cout << "A line of little consequence." << endl;

    Where.X = 4;
    ReadConsoleOutputCharacter(hOut,
                               Letters,
                               5,
                               Where,
                               &NumRead);
    cout << "5 letters starting from (4,0) ";
    cout << endl;
	cin.get(); //To see output

    return 0;
}

This is the function that I have written to try to allow python to access it:

static PyObject *
WindowsH_ReadCharacters(PyObject *self, PyObject *args)
{
	int length;
	length = 1;
	int x;
	int y;
	
	if (!PyArg_ParseTuple(args, "iii", &length, &x, &y))
		return PyInt_FromLong(1);

	char read[60000]; //I know this is a large number, I'm not sure how much the user will need.
	char *_string;
	COORD position;
	position.X = x;
	position.Y = y;

	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);

	ReadConsoleOutputCharacter(
		hOut,
		read,
		length,
		position,
		NULL);

	for(x = 0; x <= length; x++)
	{
		_string[x] = read[x];
	}



	return Py_BuildValue("s", _string);
}

Can anybody help me? Python crashes as soon as I call this. If anyone has a way that could make it better, please share, it'll help =]
And if a mod thinks this will do better in C/C++, please move it there

Dani AI

Generated

The crash and the short “\x…” output both come from a few concrete bugs in the extension code: writing from/to uninitialized pointers, not checking the API return value (so you never know how many chars were actually read), not null-terminating or using length-aware Python builders, and the Unicode/macro mismatch on Windows (ReadConsoleOutputCharacter may map to the W version when UNICODE is defined). was on the right track; ’s tip about the Tools/modulator helper is also useful for building wrappers, but the wrapper logic itself must be robust.

Checklist to fix the function

  • Validate Python args and return NULL on parse failure (don’t return arbitrary PyInts).
  • Cap and validate length (avoid huge allocations).
  • Allocate a buffer and use the API’s out-parameter to get the actual number of chars read.
  • Call the ANSI or wide API explicitly: use ReadConsoleOutputCharacterA if you want bytes, or ReadConsoleOutputCharacterW and Unicode APIs if building a Unicode/UTF-16 path.
  • Build the Python string with a length-aware call (Py_BuildValue("s#", ...) or PyString_FromStringAndSize / PyUnicode_FromWideChar) so no reliance on a C NUL terminator.
  • Free allocated memory and raise a Windows error on failure (PyErr_SetFromWindowsErr/GetLastError).

Example corrected pattern (adapt for your Python version and whether you need bytes or Unicode):

static PyObject *
WindowsH_ReadCharacters(PyObject *self, PyObject *args)
{
    int length, x, y;
    if (!PyArg_ParseTuple(args, "iii", &length, &x, &y))
        return NULL;

    if (length <= 0) {
        PyErr_SetString(PyExc_ValueError, "length must be > 0");
        return NULL;
    }
    if (length > 65536) length = 65536; /* safety cap */

    COORD pos = { (SHORT)x, (SHORT)y };
    DWORD actuallyRead = 0;
    char *buf = (char*)PyMem_Malloc((size_t)length);
    if (!buf) return PyErr_NoMemory();

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!ReadConsoleOutputCharacterA(hOut, buf, (DWORD)length, pos, &actuallyRead)) {
        PyMem_Free(buf);
        PyErr_SetFromWindowsErr(GetLastError());
        return NULL;
    }

    PyObject *res = Py_BuildValue("s#", buf, (int)actuallyRead);
    PyMem_Free(buf);
    return res;
}

Troubleshooting notes

  • If the console is redirected (pipes/files), ReadConsoleOutputCharacter will fail; check the handle with GetFileType/GetConsoleMode or use GetConsoleScreenBufferInfo to validate the coordinates.
  • If your build defines UNICODE or you want proper wide-character output to Python3, call the W variant and return a PyUnicode object instead.

Recommended Answers

All 8 Replies

Use

[/B] for C part
[code=C]
#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
HANDLE hOut;
char Letters[5];
COORD Where;
DWORD NumRead;
int i;

hOut = GetStdHandle(STD_OUTPUT_HANDLE);

cout << "A line of little consequence." << endl;

Where.X = 4;
ReadConsoleOutputCharacter(hOut,
Letters,
5,
Where,
&NumRead);
cout << "5 letters starting from (4,0) ";
cout << endl;
cin.get(); //To see output

return 0;
}

This is the function that I have written to try to allow python to access it:

static PyObject *
WindowsH_ReadCharacters(PyObject *self, PyObject *args)
{
int length;
length = 1;
int x;
int y;

if (!PyArg_ParseTuple(args, "iii", &length, &x, &y))
return PyInt_FromLong(1);

char read[60000]; //I know this is a large number, I'm not sure how much the user will need.
char *_string;
COORD position;
position.X = x;
position.Y = y;

HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);

ReadConsoleOutputCharacter(
hOut,
read,
length,
position,
NULL);
for(x = 0; x <= length; x++)
{
_string[x] = read[x];
}


return Py_BuildValue("s", _string);
}

What is your Python code you wanted to access from C?

Thanks, thought it was something else. I want to be able to call it like this:

ReadCharacters(amount, x, y) -> 
   Read the amount of characters at position x, y;
   return a string with the characters

That will call this C funtion

BOOL ReadConsoleOutputCharacter(
HANDLE hConsoleOutput, (Type Handle to Change (use STD_OUTPUT))
LPTSTR lpCharacter, (char pointer to store Characters read)
DWORD nLength, (length to read)
COORD dwReadCoord, (Type COORD to start reading at)
LPDWORD lpNumberOfCharsRead (length actually read)

I'm having a big trouble with this one. I have a ton of other functions from windowsC.h that work. I realize there is win32Console, but it doesn't include all of the functions I need. I just need a C function that will allow me to use that function in Python.

Did you check up this thing mentioned in documentation:

A more substantial example module is included in the Python source distribution as Modules/xxmodule.c. This file may be used as a template or simply read as an example. The script included in the source distribution or Windows install provides a simple graphical user interface for declaring the functions and objects which a module should implement, and can generate a template which can be filled in. The script lives in the Tools/modulator/ directory; see the README file there for more information.

I seem to not be able to find those files. Either in source or the build. I have a new dilemma. I was able to get the function to run through python, however, it now only returns a three character string of \x bits. Here's the code:

static PyObject *
WindowsH_ReadCharacters(PyObject *self, PyObject *args)
{
	DWORD length;
	int x;
	int y;
	
	if (!PyArg_ParseTuple(args, "iii", &length, &x, &y))
		return PyInt_FromLong(1);
	char* string=NULL;
	string = new char[length];
	COORD position;
	position.X = x;
	position.Y = y;

	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);

	ReadConsoleOutputCharacter(
		hOut,
		string,
		length,
		position,
		NULL);

	return PyString_FromString(string);
}

* Note that the <string> header is not included in the source.

I seem to not be able to find those files.

Modulator.py seems to exist in net at least in source files:

Right. I downloaded that package and I can't seem to find it.

Right. I downloaded that package and I can't seem to find it.

drwxrwxr-x       0 2010-03-18 23:17 Python-2.6.5/Tools/modulator/
-rw-rw-r--    1360 2003-10-24 22:09 Python-2.6.5/Tools/modulator/EXAMPLE.py
-rwxrwxr-x    4824 2004-07-18 08:16 Python-2.6.5/Tools/modulator/genmodule.py
-rwxrwxr-x   14438 2004-07-18 08:16 Python-2.6.5/Tools/modulator/modulator.py
-rw-rw-r--     980 1999-02-16 18:19 Python-2.6.5/Tools/modulator/README
-rw-rw-r--    1477 2003-10-24 22:09 Python-2.6.5/Tools/modulator/ScrolledListbox.py
drwxrwxr-x       0 2010-03-18 23:17 Python-2.6.5/Tools/modulator/Templates/
-rw-rw-r--       0 2000-09-02 01:29 Python-2.6.5/Tools/modulator/Templates/copyright
-rw-rw-r--     113 1995-06-20 20:45 Python-2.6.5/Tools/modulator/Templates/mod
.................... etc ................................

Oh okay, I was looking in the wrong place xD
I'll take a look, thank you

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.