Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>

using namespace cv;
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    return p;
}

int free_img(char *c)
{
    if (nullptr != c)
    {
        delete[] c;
        c = nullptr;
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())

lib = ct.CDLL("void_dll.dll")
func = lib.alloc_img
func.restype = ct.c_char_p

bytes_array = func(ct.c_char_p(s.encode("utf-8")), width, height)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>

using namespace cv;
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    return p;
}

int free_img(char *c)
{
    if (nullptr != c)
    {
        delete[] c;
        c = nullptr;
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())

lib = ct.CDLL("void_dll.dll")
func = lib.alloc_img
func.restype = ct.c_char_p

bytes_array = func(ct.c_char_p(s.encode("utf-8")), width, height)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>

using namespace cv;
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    return p;
}

Python code:

import ctypes as ct
import numpy as np

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())

lib = ct.CDLL("void_dll.dll")
func = lib.alloc_img
func.restype = ct.c_char_p

bytes_array = func(ct.c_char_p(s.encode("utf-8")), width, height)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>

using namespace cv;
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height)
*height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;


            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
 img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
func alloc_img = lib.alloc_img
func.restype free_img = lib.free_img
alloc_img.restype = ct.c_char_p

bytes_array = func(ct.c_char_p(s.encode("utf-8")), alloc_img(ct.c_char_p(s.encode("utf-8")), width, height)
height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;


            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
alloc_img.restype = ct.c_char_p

w = int(ct.c_long(width.contents).value)

h = int(ct.c_long(height.contents).value)


bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (w, h)

#numpy_array = np.reshape(numpy_array, (width.contents, height.contents))

cv2.imshow("Frame", numpy_array)
cv2.waitKey(0)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;


            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
alloc_img.restype = ct.c_char_p

w = int(ct.c_long(width.contents).value)

h = int(ct.c_long(height.contents).value)


bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (w, h)

#numpy_array = np.reshape(numpy_array, (width.contents, height.contents))
(width.contents.value, height.contents.value)

cv2.imshow("Frame", numpy_array)
cv2.waitKey(0)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;


            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cv2.imshow("Frame", numpy_array)
cv2.waitKey(0)

print(len(numpy_array))
print(numpy_array)
print(width.contents)
print(height.contents)

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;
 
            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cv2.imshow("Frame", numpy_array)
cv2.waitKey(0)
cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;


DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;

            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
            return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    delete[] p;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <mutex>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;
 mutex rw_ids;

DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    rw_ids.lock();
    ids[ids.size()] = p;
    *image_id = ids.size() - 1;
    rw_ids.unlock();

    cout << "Created img id " << *image_id << endl;

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;

            rw_ids.lock();

            if (nullptr != ci->second)
            {
                delete[] ci->second;
            }

            ids.erase(ci);
 
            rw_ids.unlock();

            return 0;
        }
    }

    return 1;
        }
    }

    return 0;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    delete[] p;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Input image:

image description

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <mutex>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;
mutex rw_ids;

DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    rw_ids.lock();

    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;
        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    rw_ids.lock();
    ids[ids.size()] = p;
    *image_id = ids.size() - 1;
    rw_ids.unlock();

    cout << "Created img id " << *image_id << endl;

    rw_ids.unlock();

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    rw_ids.lock();

    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;

            rw_ids.lock();

            if (nullptr != ci->second)
                delete[] ci->second;

            ids.erase(ci);

            rw_ids.unlock();
             return 0;
        }
    }

    rw_ids.unlock();

    return 1;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    delete[] p;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a numpy array:

Input image:

image description

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <mutex>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;
mutex rw_ids;

DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    rw_ids.lock();

    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;

        rw_ids.unlock();

        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    rw_ids.unlock();

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    rw_ids.lock();

    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;

            if (nullptr != ci->second)
                delete[] ci->second;

            ids.erase(ci);

            rw_ids.unlock();
             return 0;
        }
    }

    rw_ids.unlock();

    return 1;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    delete[] p;

    return 0;
}

I exported a DLL function that returns a char* array. The Python code calls the function and converts the bytes into a 2D numpy array:array, and back again to bytes:

Input image:

image description

Windows code:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <mutex>
using namespace std;


#define DLLEXPORT extern "C" __declspec(dllexport)


map<size_t, char*> ids;
mutex rw_ids;

DLLEXPORT int get_img_from_char_array(char *c, int *width, int *height)
{
    Mat frame_content(*height, *width, CV_8UC1, c);

    return 0;
}


DLLEXPORT char *alloc_img(const char *file_name, int *width, int *height, size_t *image_id)
{
    rw_ids.lock();

    Mat img = imread(file_name, IMREAD_GRAYSCALE);

    if (img.empty())
    {
        *width = 0;
        *height = 0;

        rw_ids.unlock();

        return nullptr;
    }

    *width = img.cols;
    *height = img.rows;

    size_t num_pixels = (*width)*(*height);

    char *p = new char[num_pixels];
    memcpy(p, img.data, num_pixels*sizeof(char));

    ids[ids.size()] = p;
    *image_id = ids.size() - 1;

    cout << "Created img id " << *image_id << endl;

    rw_ids.unlock();

    return p;
}

DLLEXPORT int free_img(size_t *image_id)
{
    rw_ids.lock();

    for (map<size_t, char*>::const_iterator ci = ids.begin(); ci != ids.end(); ci++)
    {
        if (ci->first == *image_id)
        {
            cout << "Deleted img id " << *image_id << endl;

            if (nullptr != ci->second)
                delete[] ci->second;

            ids.erase(ci);

            rw_ids.unlock();

            return 0;
        }
    }

    rw_ids.unlock();

    return 1;
}

Python code:

import ctypes as ct
import numpy as np
import cv2

ptr = ct.c_char_p()
s = "dove.png"
width = ct.pointer(ct.c_int())
height = ct.pointer(ct.c_int())
img_id = ct.pointer(ct.c_size_t())
lib = ct.CDLL("void_dll.dll")
alloc_img = lib.alloc_img
free_img = lib.free_img
get_img_from_char_array = lib.get_img_from_char_array

alloc_img.restype = ct.c_char_p

bytes_array = alloc_img(ct.c_char_p(s.encode("utf-8")), width, height, img_id)
numpy_array = np.frombuffer(bytes_array, dtype=np.uint8)
numpy_array.shape = (width.contents.value, height.contents.value)

cppbytes = numpy_array.tobytes()
get_img_from_char_array(cppbytes, width, height);

free_img(img_id)

I also have some extra code handy, which uses a void** pointer to allocate memory:

int func(void **ptr)
{
    float *p = new float[50];
    p[0] = 123.456;
    *ptr = p;

    return 0;
}

int main(void)
{
    float *p = 0;
    func(reinterpret_cast<void**>(&p));

    cout << p[0] << endl;

    delete[] p;

    return 0;
}