Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 93355
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 10, 20262026-05-10T23:19:53+00:00 2026-05-10T23:19:53+00:00

I am trying to use Python’s ctypes library to access some methods in the

  • 0

I am trying to use Python’s ctypes library to access some methods in the scanning library SANE. This is my first experience with ctypes and the first time I have had to deal with C datatypes in over a year so there is a fair learning curve here, but I think even without that this particular declaration would be troublesome:

extern SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); 

First of all, I’ve successfully dealt with SANE_Status (an enum) and SANE_Bool (a typedef to c_int). Those were both simple. That first parameter, on the other hand, is causing me all sorts of grief. I’m unfamiliar with the ‘***‘ notation to begin with and my tracer bullets so far have yielded nothing more than garbage data. How do I format the input to this function such that I can read back a list of my Python structure-objects? For reference, the C structure being referenced is:

typedef struct {     SANE_String_Const name; /* unique device name */     SANE_String_Const vendor;   /* device vendor string */     SANE_String_Const model;    /* device model name */     SANE_String_Const type; /* device type (e.g., 'flatbed scanner') */  } SANE_Device; 

Where SANE_String_Const is defined as a c_char_p.

My Python/ctypes version of this object is:

class SANE_Device(Structure):     _fields_ = [         ('name', c_char_p),         ('vendor', c_char_p),         ('model', c_char_p),         ('type', c_char_p)] 

Suggestions on what I should pass in such that I can get the expected behavior (a list of structure-objects) out of this? All responses appreciated.

Update 1:

Using the following, I was able to retrieve a correct SANE_Device Python structure:

devices = pointer(pointer(pointer(SANE_Device()))) status = libsane.sane_get_devices(devices, c_int(0)) print status, devices, devices.contents.contents.contents.name 

However, 1) yuck and 2) that seems like it would only work if there is a single result. I can’t len() on devices.contents.contents or devices.contents.contents.contents. How am I to determine the number of results? The SANE docs specify that ‘If the function executes successfully, it stores a pointer to a NULL terminated array of pointers to SANE_Device structures in *device_list’. Suggestions?

Update 2:

I was able to pass an ten-item array and then access the first element using:

devices = pointer(pointer(pointer((SANE_Device * 10)()))) status = libsane.sane_get_devices(devices, c_int(0)) print status, devices, devices.contents.contents.contents[0].name 

However, ten is obviously an arbitrary number and I have no way of determining the actual number of results. Trying to access devices.contents.contents.contents[1].name when only one device is connected causes a segmentation fault. There must be a proper way of dealing with variable-length constructs like these in ctypes.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-10T23:19:53+00:00Added an answer on May 10, 2026 at 11:19 pm

    A const SANE_Device *** is a three-level pointer: it’s a pointer to a pointer to a pointer to a constant SANE_Device. You can use the program cdecl to decipher complicated C/C++ type definitions.

    According to the SANE documentation, SANE_get_devices() will store a pointer to a NULL-terminated list of pointers to SANE devices if successful. Thus, the proper way to call it is to declare a variable of type const SANE_Device ** (i.e. a pointer to a pointer to a constant `SANE_Device), and pass in the address of that pointer:

    const SANE_Device **device_list; SANE_get_devices(&device_list, local_only);  // check return value // Now, device_list[0] points to the first device, // device_list[1] points to the second device, etc. // Once you hit a NULL pointer, that's the end of the list: int num_devices = 0; while(device_list[num_devices] != NULL)     num_devices++; // num_devices now stores the total number of devices 

    Now, this is how you would call it from C code. I’ve skimmed the documentation on ctypes, and it appears that you want to use the byref function to pass the argument by reference, and that the value you pass should be a POINTER to a POINTER to a SANE_Device. Note the distinction between pointer and POINTER: the former creates a pointer to an instance, whereas the latter creates a pointer to a type. Thus, I’m guessing the following code will work:

    // SANE_Device declared as you had it devices = POINTER(POINTER(SANE_Device))()  // devices is a NULL pointer to a pointer to a SANE_Device status = libsane.sane_get_devices(byref(devices), c_int(0)) if status != successful:   // replace this by whatever success is     print error else:     num_devices = 0     // Convert NULL-terminated C list into Python list     device_list = []     while devices[num_devices]:         device_list.append(devices[num_devices].contents)  // use .contents here since each entry in the C list is itself a pointer         num_devices += 1     print device_list 

    [Edit] I’ve tested the above code using a very simple placeholder for SANE_get_devices, and it works.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 58k
  • Answers 58k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • added an answer One option would have a function that returns a list… May 11, 2026 at 8:40 am
  • added an answer I don't think WPF has any built in support for… May 11, 2026 at 8:40 am
  • added an answer If you compile your ASP.NET application then you can omit… May 11, 2026 at 8:40 am

Top Members

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.

      Related Questions

      No related questions found