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

Add primitive c/CXType_FunctionNoProto parsing #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

maersdal
Copy link

@maersdal maersdal commented Mar 1, 2025

Adds support for parsing int foo() like functions as zero-argument functions.

Added because I encountered a library that used one of these and would not parse without it.

I'm pretty certain this is not the best way of doing this. But it's an auto-tool so what can you do.

Adds support for parsing `int foo()` like functions as zero-argument functions.

Added because I encountered a library that used one of these and would not parse without it.

I'm pretty certain this is not the best way of doing this. But it's an auto-tool so what can you do.
@phronmophobic
Copy link
Owner

Thanks for the pull request!

A couple thoughts:

The data representation in the pull request is [:coffi.ffi/fn-no-proto arg-types ret-type] where arg-types is always the empty vector. Does it make sense to leave out arg-types from the data definition?

The coercer for passing this type to a function will always convert to a zero arity callback function. I'm still a little fuzzy on how these types are used in the wild, but coercing to a zero arity callback seems like it's usually wrong. Maybe we should just coerce the same way we coerce pointers and let users decide how to convert to callbacks if necessary?

Do you have a link to where this pops up in the library you're using? It would be nice to have at least one example use case as a reference.

@phronmophobic
Copy link
Owner

Had a discussion in #coffi on slack. One suggestion was to use a namespaced keyword for the type outside of the coffi namespace, which I think makes sense. Rather than :coffi.ffi/fn-no-proto, we should use :com.phronemophobic.clong.clang/fn-no-proto.

@maersdal
Copy link
Author

maersdal commented Mar 6, 2025

Thanks for the pull request!
...
Do you have a link to where this pops up in the library you're using? It would be nice to have at least one example use case as a reference.

The guilty function
INGESCAPE_EXPORT void igs_log_set_syslog(bool);

Interestingly enough, that function has a boolean parameter. So my spidey sense is tingling here. Might be a deeper issue? I'm way out of my depth here.

Found it via

(def api' (clang/easy-api "~/dev/ingescape/include/ingescape.h"))
(->> api'
     :functions 
     (filter (fn [{:keys [type]}]
               (= type "CXType_FunctionNoProto"))))

So I might be doing something wrong...

The data representation in the pull request is [:coffi.ffi/fn-no-proto arg-types ret-type] where arg-types is always the empty vector. Does it make sense to leave out arg-types from the data definition?

The coercer for passing this type to a function will always convert to a zero arity callback function. I'm still a little fuzzy on how these types are used in the wild, but coercing to a zero arity callback seems like it's usually wrong. Maybe we should just coerce the same way we coerce pointers and let users decide how to convert to callbacks if necessary?

Pointers sound more sane. I agree.

we should use :com.phronemophobic.clong.clang/fn-no-proto.

Yes.

@maersdal
Copy link
Author

maersdal commented Mar 6, 2025

Actually, all bool parameter fns in that library gets the same type. So it might be me calling easy-api wrong. Here is the full list:

{:args [],
  :ret {:spelling "void"},
  :function/args [],
  :symbol "igs_log_set_console",
  :function/ret :coffi.mem/void,
  :type "CXType_FunctionNoProto",
  :linkage "CXLinkage_External",
  :id :igs_log_set_console,
  :raw-comment nil,
  :kind "CXCursor_FunctionDecl",
  :spelling "igs_log_set_console"}
 {:args [],
  :ret {:spelling "void"},
  :function/args [],
  :symbol "igs_log_set_syslog",
  :function/ret :coffi.mem/void,
  :type "CXType_FunctionNoProto",
  :linkage "CXLinkage_External",
  :id :igs_log_set_syslog,
  :raw-comment nil,
  :kind "CXCursor_FunctionDecl",
  :spelling "igs_log_set_syslog"}
 {:args [],
  :ret {:spelling "void"},
  :function/args [],
  :symbol "igs_log_set_console_color",
  :function/ret :coffi.mem/void,
  :type "CXType_FunctionNoProto",
  :linkage "CXLinkage_External",
  :id :igs_log_set_console_color,
  :raw-comment nil,
  :kind "CXCursor_FunctionDecl",
  :spelling "igs_log_set_console_color"}
 {:args [],
  :ret {:spelling "void"},
  :function/args [],
  :symbol "igs_log_set_stream",
  :function/ret :coffi.mem/void,
  :type "CXType_FunctionNoProto",
  :linkage "CXLinkage_External",
  :id :igs_log_set_stream,
  :raw-comment nil,
  :kind "CXCursor_FunctionDecl",
  :spelling "igs_log_set_stream"}
 {:args [],
  :ret {:spelling "void"},
  :function/args [],
  :symbol "igs_log_set_file",
  :function/ret :coffi.mem/void,
  :type "CXType_FunctionNoProto",
  :linkage "CXLinkage_External",
  :id :igs_log_set_file,
  :raw-comment nil,
  :kind "CXCursor_FunctionDecl",
  :spelling "igs_log_set_file"}

@phronmophobic
Copy link
Owner

My guess is the problem is that some of the system paths aren't included. You can workaround this using the first bullet point from https://github.com/phronmophobic/clong?tab=readme-ov-file#tips. Extra arguments can be passed as the second optional argument to easy-api as well as parse.

I really want to include the system paths by default, but the version of LLVM that I used doesn't offer any way to do that. I think listing the default system arguments from the programmatic API was on the LLVM roadmap, but I'm not sure if that feature ever got implemented.

I include some default args, but they're tied to a specific version on mac osx. They shouldn't hurt if provided, but they don't help if you're on linux or have a different clang toolchain installed.

@phronmophobic
Copy link
Owner

Ok, it seems like the name for the API to get default args is under LibTooling, which is only available via the c++ API? https://clang.llvm.org/docs/LibTooling.html

It seems like it's also coupled to trying to run tooling out of the LLVM project directory, llvm/llvm-project#64834.

@phronmophobic
Copy link
Owner

Maybe there's a good there's a way to improve the docs or API to either warn or avoid this issue?

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

Successfully merging this pull request may close these issues.

2 participants