-3

i am trying to convert my python code to dll using cffi so i can access this code in my c# apllication, and i am trying to send image my c# code to python function, below is my code to read the file and convert to bytes array

[DllImport(@"plugin-1.5.dll", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr test2(byte[] img, StringBuilder url);
void call(){
StringBuilder sb = new StringBuilder(20);
sb.Append("test");

Bitmap target = (Bitmap)Bitmap.FromFile(@"C:\Users\LaserTrac\Desktop\lala_192_1.jpg");
            ImageFormat fmt = new ImageFormat(target.RawFormat.Guid);
            var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == target.RawFormat.Guid);
            //this is for situations, where the image is not read from disk, and is stored in the memort(e.g. image comes from a camera or snapshot)
            if (imageCodecInfo == null)
            {
                fmt = ImageFormat.Jpeg;
            }
            byte[] image_byte_array = null;
            long length = 0;
            //Image img = Image.FromFile(@"");
            using (MemoryStream ms = new MemoryStream())
            {
                target.Save(ms, fmt);
                image_byte_array = ms.ToArray();
                length = ms.Length;
            }
test2(image_byte_array, sb);
}

and below is my code in python what i tried , plugin.h

extern char* test2(unsigned char*, char* url);

python file

@ffi.def_extern()
    def test2(img, url):
        print(img)
        url = ffi.string(url)
        #img1 = Image.open(io.BytesIO(ffi.string(img)))
        #img1.save("lala1.jpg")
        decoded = cv2.imdecode(np.frombuffer(ffi.buffer(img)))
        #img_np = cv2.imdecode(ffi.buffer(img), cv2.IMREAD_COLOR)
        cv2.imwrite("filename.jpg", decoded) 
        p = ffi.new("char[]", "test".encode('ascii'))
        return p

error i got is buffer size must be a multiple of element size how can i convert this img object to any python image object

in the code above when i tried below code

img_np = cv2.imdecode(ffi.buffer(img), cv2.IMREAD_COLOR)

i got type error in test2 TypeError: Expected Ptr<cv::UMat> for argument 'buf'

and with this line decoded = cv2.imdecode(np.frombuffer(ffi.buffer(img))) i got ValueError ValueError: buffer size must be a multiple of element size

a workaround is i can convert image to base64 string and string and int variables are working, but i am also looking this to work because i have done this in c++ dll, and for some reason i am trying to convert my python code to dll.

Rawat
  • 461
  • 3
  • 6
  • 23
  • Please give a full traceback, not just an error message. We don't know which line produces it. – Armin Rigo Sep 15 '20 at 11:16
  • @ArminRigo , sorry for the late reply, i have update my question please have a look, overall i am trying to send image from c# to this python code and trying to convert c# byte[] to python cv2 image object – Rawat Sep 22 '20 at 13:21
  • I answered your question, but note that there is another problem: you can't usually return a ``char *`` from C, because the memory pointed by the returned pointer will either leak or (like here) be freed automatically before the C# code has got a change to read it. Instead you need the more painful way of guessing how large a buffer the function will return, and allocating and passing this buffer from the caller. – Armin Rigo Sep 23 '20 at 17:54

1 Answers1

0

ffi.buffer(p) must return a buffer of some size. If p was of an known-length array type like char[100] then it would return a buffer of 100 bytes. If it was pointing to a struct, i.e. of type mystruct_t *, then it would be of size sizeof(mystruct_t). But here it is a unsigned char *, so the returned buffer contains only sizeof(unsigned char) bytes, i.e. a single byte.

Use instead the ffi.buffer(p, size) variant. To know the size, pass the length variable as an extra argument from C# to Python.

Armin Rigo
  • 12,048
  • 37
  • 48