Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

const qualifiers in pubic API #845

Open
martinjrobins opened this issue Jun 27, 2024 · 7 comments
Open

const qualifiers in pubic API #845

martinjrobins opened this issue Jun 27, 2024 · 7 comments
Labels
enhancement New feature or request

Comments

@martinjrobins
Copy link

Is your feature request related to a problem? Please describe.

I'm writing a rust sys crate that uses bindgen to automatically generate rust bindings for suitesparse. At the moment when wrapping a function like klu_analyze in the KLU solver, raw pointers are wrapped as mutable pointers *mut T, e.g: the C function

KLU_symbolic *KLU_analyze       /* returns NULL if error, or a valid
                                   KLU_symbolic object if successful */
(
    /* inputs, not modified */
    Int n,              /* A is n-by-n */
    Int Ap [ ],         /* size n+1, column pointers */
    Int Ai [ ],         /* size nz, row indices */
    /* -------------------- */
    KLU_common *Common
)

becomes

extern "C" {
    pub fn klu_analyze(
        n: i32,
        Ap: *mut i32,
        Ai: *mut i32,
        Common: *mut klu_common_,
    ) -> *mut klu_symbolic_;
}

This is an issue because the arguments Ap and Ai are incorrectly marked as mutable, causing problems downstream for users who are then required to have mutable handles to Ap and Ai. This can be corrected by marking the arguments Ap and Ai in the C signature as const, for example:

KLU_symbolic *KLU_analyze       /* returns NULL if error, or a valid
                                   KLU_symbolic object if successful */
(
    /* inputs, not modified */
    Int n,              /* A is n-by-n */
    Int Ap [const],         /* size n+1, column pointers */
    Int Ai [const],         /* size nz, row indices */
    /* -------------------- */
    KLU_common *Common
)

which would then generate the correct rust function signature with Ap and Ai marked as `const.

Are there any plans to explicitly use const qualifiers in suitesparse rather than relying on comments like this? Would you be happy if I put together a PR adding this to the functions that I need?

Describe the solution you'd like

Use explicit const qualifiers in public facing functions.

Describe alternatives you've considered

The alternative is for the bindings for suitesparse be manually implemented, rather than relying on automated tools.

@mmuetzel
Copy link
Contributor

I agree with your point. It would probably be best if function arguments that are pointers (or arrays) to variables that aren't allowed to be changed by the function were marked as const.

However, are you sure that Int Ap[const] is valid C syntax? Shouldn't it be const Int Ap[] instead?

@martinjrobins
Copy link
Author

martinjrobins commented Jun 30, 2024

I believe you can do Int Ap[const] since C99 (https://en.cppreference.com/w/c/language/const#:~:text=In%20a%20function%20declaration%2C%20the,the%20array%20type%20is%20transformed.), but I'm not sure as this is the first time I've come across this syntax. Presumably const Int Ap[] is equivilent?

UPDATE: actually, after looking at https://en.cppreference.com/w/c/language/array I think const Int Ap[] is a pointer to an array of const Int values, whereas Int Ap[const] is a const pointer to an array of Int values, so I think you are correct it should be const Int Ap[], or perhaps even const Int Ap[const].

@DrTimothyAldenDavis
Copy link
Owner

This will take me quite a while to resolve, since I would need to revise all APIs to essentially all my packages. It might also require an SO change to all my packages as well. But I'll consider it for the future.

@DrTimothyAldenDavis DrTimothyAldenDavis added the enhancement New feature or request label Aug 6, 2024
@gruenich
Copy link
Contributor

Cppcheck detects pointer that are not modified and proposes a modification of the function signature. Tim, tell me one library to begin with and I will create an according merge request. From the changes you will have a good starting point what to revise. Are you interested?

@DrTimothyAldenDavis
Copy link
Owner

DrTimothyAldenDavis commented Oct 29, 2024 via email

@gruenich
Copy link
Contributor

Tim, I see you concerns. What about a less disruptive approach using a toggle?

  1. Introduce a C pre-processor macro SS_API_CONST
  2. Introduce another C pre-processor macro and similar named CMake variable STRICT_API_CONST
  3. Add this code at a central point:
    #ifdef STRICT_API_CONST
    #define SS_API_CONST const
    #else
    #define SS_API_CONST
    #endif
  1. We can modify the public API like in
KLU_symbolic *KLU_analyze       /* returns NULL if error, or a valid
                                   KLU_symbolic object if successful */
(
    /* inputs, not modified */
    Int n,              /* A is n-by-n */
    SS_API_CONST Int Ap [ ],         /* size n+1, column pointers */
    SS_API_CONST Int Ai [ ],         /* size nz, row indices */
    /* -------------------- */
    KLU_common *Common
)
  1. By default, the API remains unchanged. If a user wants to use the improved API, she has to set the toggle.
  2. In SuiteSparse 8 or 9 you can decide to activate the toggle always, and later replace every SS_API_CONST by const in SuiteSparse.

By the way, at SuperLU we have a similar discussion and currently no solution. The claim is that when the interfaces introduces consts, the user code can rely on this and be written to be a little bit faster. See xiaoyeli/superlu#142

@DrTimothyAldenDavis
Copy link
Owner

Got it. That would be much less disruptive. Would the API changes be limited to just adding the const?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants