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

How does this project work? #103

Closed
jcbhmr opened this issue Jun 9, 2023 · 8 comments
Closed

How does this project work? #103

jcbhmr opened this issue Jun 9, 2023 · 8 comments

Comments

@jcbhmr
Copy link

jcbhmr commented Jun 9, 2023

I'd be interested in learning more about how this project works. Some questions:

  • What's the .m file? Beginner here. I googled and "An M file is a class implementation file used by programs written in Objective-C"
  • Is this project written in .c or .cpp?
  • What's the high-level overview of what this project does? Is it basically a wrapper with #ifdef WINDOWS cascades for each platform?
  • What's gtk?

Why I'm curious: I'm interested in making a JavaScript wrapper around this API using https://napi.rs/ and https://github.com/btzy/nfde-rs and I was curious about some of the design decisions behind that Rust wrapper and that lead me to be curious about the design of the original library.

@btzy
Copy link
Owner

btzy commented Jun 10, 2023

Hey,

That's a lot of questions.

What's the .m file? Beginner here. I googled and "An M file is a class implementation file used by programs written in Objective-C"
Is this project written in .c or .cpp?

This project has a C interface. (This interface is nfd.h.) This means that after compiling this project into a static or shared library, you can use it with anything that knows how to call C code. C is the lingua franca of desktop programming, so almost any general-purpose programming language (including C++, Rust, Python, and JavaScript (NodeJS)) will have a way of calling C interfaces. For interpreted and garbage-collected languages like Python and JavaScript, this usually involves writing some boilerplate code (or autogenerating them using some tools) to marshal objects across languages.

This project is implemented in C++ (for Windows and Linux) and Objective-C (for MacOS). This means that to compile this project from source, you need to use a C++ or Objective-C compiler, depending that platform you are compiling for. (The nfd_cocoa.m file is the implementation for MacOS.) The required compilers are the standard compilers for each of the three operating systems, and can be downloaded easily for free from their official websites (or for Linux, it should come pre-installed). Once compiled into a static or shared library, however, its interface looks and behaves like a C library.

What's the high-level overview of what this project does? Is it basically a wrapper with #ifdef WINDOWS cascades for each platform?
What's gtk?

I'm not sure what you're asking for here; the README should cover most high-level things. There are 3 .cpp files and 1 .m file in the src directory, and for each platform you will compile exactly one of those files. For Linux there are two implementations, GTK and Portal. Linux doesn't have a file dialog baked into the operating system, and most programs will use GTK (a GUI library) to show a file dialog. Portal is an interface on Linux that allows other GUI libraries (most notably KDE) to register themselves, so that applications can show their dialogs instead of GTK ones; this needs cooperation from applications because they need to open the file dialog through this interface, instead of directly calling GTK. The "Portal" implementation opens the file through this interface, and the "GTK" implementation calls GTK directly.

Why I'm curious: I'm interested in making a JavaScript wrapper around this API using https://napi.rs/ and https://github.com/btzy/nfde-rs and I was curious about some of the design decisions behind that Rust wrapper and that lead me to be curious about the design of the original library.

I would recommend trying to write/generate a JavaScript wrapper for this project directly, instead of trying to wrap nfde-rs. This is because nfde-rs is already a wrapper for this project, and having multiple wrapper layers add more dependencies (i.e. to build a JavaScript wrapper for nfde-rs, you will need a Rust compiler, on top of CMake and a C++/Objective-C compiler). I haven't checked this, but I would imagine that there are officially-supported ways to call a C library from NodeJS/Javascript, and so there is no need to go from JavaScript to Rust (which likely involves stepping through a C interface anyway).

@jcbhmr
Copy link
Author

jcbhmr commented Jun 10, 2023

What's the high-level overview of what this project does? Is it basically a wrapper with #ifdef WINDOWS cascades for each platform?

I'm not sure what you're asking for here; the README should cover most high-level things.

I was kinda getting at "how do you magically make it use the right implementation on my system?" 😊 From university classes in C++, I've seen this kind of pattern:

int main() {
  #ifdef WINDOWS
    std::cout << "Windows!\n";
  #endif
  #ifdef MACOS
    std::cout << "macOS!\n";
  #endif
  #ifdef LINUX
    std::cout << "Linux!\n";
  #endif
}

I think that's all done in the CMakeLists.txt in this project's case?

if(nfd_PLATFORM STREQUAL PLATFORM_WIN32)
list(APPEND SOURCE_FILES nfd_win.cpp)
endif()

if(nfd_PLATFORM STREQUAL PLATFORM_LINUX)

if(nfd_PLATFORM STREQUAL PLATFORM_MACOS)

For more context on my background: When I used "advanced C++" like terminal GUI libraries + HTTP stuff, etc, I used xmake since I found cmake too complicated 😂 https://xmake.io/#/getting_started

@jcbhmr
Copy link
Author

jcbhmr commented Jun 10, 2023

I would recommend trying to write/generate a JavaScript wrapper for this project directly, instead of trying to wrap nfde-rs. This is because nfde-rs is already a wrapper for this project, and having multiple wrapper layers add more dependencies (i.e. to build a JavaScript wrapper for nfde-rs, you will need a Rust compiler, on top of CMake and a C++/Objective-C compiler). I haven't checked this, but I would imagine that there are officially-supported ways to call a C library from NodeJS/Javascript, and so there is no need to go from JavaScript to Rust (which likely involves stepping through a C interface anyway).

One of the reasons I gravitated to the Rust version was because https://napi.rs/ seems so easy to wrap stuff! 😱

image

vs

image

@jcbhmr
Copy link
Author

jcbhmr commented Jun 10, 2023

unrelated question about CI:
Does the circle ci config do anything, or is everything GitHub Actions now? Do you use CircleCI and GitHub actions together? I note that the GitHub actions workflow seems to be a good deal larger than circle ci.

@guest271314
Copy link

If you want to work in C and JavaScipt you can use QuickJS which provides a means to import compiled shared object files intothe QuickJS environment.

@btzy
Copy link
Owner

btzy commented Jun 13, 2023

What's the high-level overview of what this project does? Is it basically a wrapper with #ifdef WINDOWS cascades for each platform?

I'm not sure what you're asking for here; the README should cover most high-level things.

I was kinda getting at "how do you magically make it use the right implementation on my system?" 😊 From university classes in C++, I've seen this kind of pattern:

int main() {
  #ifdef WINDOWS
    std::cout << "Windows!\n";
  #endif
  #ifdef MACOS
    std::cout << "macOS!\n";
  #endif
  #ifdef LINUX
    std::cout << "Linux!\n";
  #endif
}

I think that's all done in the CMakeLists.txt in this project's case?

Yes that's right. There's no need to keep them in the same file when the four implementations are mostly different from each other. Also, it's impossible for macOS since it has to be in Objective-C instead of C++.

@btzy
Copy link
Owner

btzy commented Jun 13, 2023

unrelated question about CI:
Does the circle ci config do anything, or is everything GitHub Actions now? Do you use CircleCI and GitHub actions together? I note that the GitHub actions workflow seems to be a good deal larger than circle ci.

I added CircleCI at some point because GitHub Actions didn't support macOS 12, and I wanted to make sure it worked over there. Now it's redundant, since GitHub supports macOS 12.

@jcbhmr
Copy link
Author

jcbhmr commented Jun 13, 2023

Thanks for your insight! The one thing about this project that seems to be a bit "nonstandard"-enough that might be worthy of putting in the wiki (judging from response in #106) is the part about how instead of #ifdef magic, you use CMake if(nfd_PLATFORM...) magic to compile one file from the src/ folder.

I'm closing this issue since you've answered my questions. Thanks for taking time out of your day to educate me! ❤️

@jcbhmr jcbhmr closed this as completed Jun 13, 2023
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

No branches or pull requests

3 participants