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

Repo currently doesn't work for C code... #1225

Open
GordonBGood opened this issue Dec 3, 2024 · 6 comments
Open

Repo currently doesn't work for C code... #1225

GordonBGood opened this issue Dec 3, 2024 · 6 comments

Comments

@GordonBGood
Copy link

My main interest in this project is to be able to use webkit from C on all three supported platforms. Although the example compiling from the C++ examples works as described in the README file, changing to trying to compile the C equivalent fails at the linking stage with undefined reference to webview_create, webview_set_title, webview_set_size, webview_set_html, webview_run, and webview_destroy for the basic example and I'm sure that there will be more for the more extensive "bind" example; in other words, all of the C WebView API isn't found and isn't linked...

What OS are you using (uname -a, or Windows version)?

What programming language are you using (C/C++/Go/Rust)?

I don't think the OS or versions of the compilers matter for this problem, but for completeness sake they are as follows:

  1. The OS is Fedora Linux 4: Linux gordonbgoodbeelink 6.11.8-300.fc41.x86_64 Fix Win64 compilation issues #1 SMP PREEMPT_DYNAMIC Thu Nov 14 20:37:39 UTC 2024 x86_64 GNU/Linux
  2. The compiler I tried this with was GCC: gcc (GCC) 14.2.1 20240912 (Red Hat 14.2.1-3).

However, as I said, I can't see that this problem is related to either the Operating System or the compiler used but rather that the build process as specified isn't complete.

What did you expect to see and what you saw instead?

The command line I used to attempt to compile, just slightly modified from the recommended C++ command line, was as follows (run from the examples directory):

gcc basic.c -O2 -I../core/include -Ilibs $(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1) -ldl -o basic_example

It seems that for C there is no definition for the webkit interface API as those seem to only be defined for C++ and therefore there is no library to be linked against...

The complete error message is as follows:

/usr/bin/ld: /tmp/cc52x5pb.o: in function main': basic.c:(.text.startup+0x6): undefined reference to webview_create'
/usr/bin/ld: basic.c:(.text.startup+0x16): undefined reference to webview_set_title' /usr/bin/ld: basic.c:(.text.startup+0x2a): undefined reference to webview_set_size'
/usr/bin/ld: basic.c:(.text.startup+0x37): undefined reference to webview_set_html' /usr/bin/ld: basic.c:(.text.startup+0x3f): undefined reference to webview_run'
/usr/bin/ld: basic.c:(.text.startup+0x47): undefined reference to `webview_destroy'
collect2: error: ld returned 1 exit status

I expected to see this compile and link without errors...

@SteffenL
Copy link
Collaborator

SteffenL commented Dec 3, 2024

This is a C++ library with a C interface. Therefore the library must be compiled with a C++ compiler. You can then link it and use the C interface.

Would you like an example?

@GordonBGood
Copy link
Author

@SteffenL,

Thanks for your reply. I understand that this is a C++ library, and tried the procedure from your repo specifically using a C source file as Your webview_c rep and that didn't seem to work either, even after fixing the missing file target for the "wget" and making all of the includes work out so I must be missing something...

I still get the same missing references on link...

Yes, a working example would be useful...

@SteffenL
Copy link
Collaborator

SteffenL commented Dec 3, 2024

Haven't worked on that particular project and I'm not sure it's useful anymore.

There are examples in this repo's readme file but if you don't want to use CMake then here's a simple example for Linux that invokes the compiler directly.

main.c:

#include "webview/webview.h"
#include <stddef.h>

int main(void) {
  webview_t w = webview_create(0, NULL);
  webview_set_title(w, "Basic Example");
  webview_set_size(w, 480, 320, WEBVIEW_HINT_NONE);
  webview_set_html(w, "Thanks for using webview!");
  webview_run(w);
  webview_destroy(w);
  return 0;
}
git clone --branch 0.12.0 https://github.com/webview/webview.git subprojects/webview
mkdir build
g++ --shared -fPIC subprojects/webview/core/src/webview.cc -O2 --std=c++11 -Isubprojects/webview/core/include $(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1) -ldl -DWEBVIEW_BUILD_SHARED -o build/libwebview.so
gcc main.c -O2 --std=c99 -Isubprojects/webview/core/include -DWEBVIEW_SHARED build/libwebview.so -o build/main
build/main

If you go this route then you should take the RPATH into consideration, and you need to make adjustments if you don't want a shared library.

@GordonBGood
Copy link
Author

@SteffenL,

Thanks for your working example; following that lead, I can now compile with either shared or static libraries with C source as the main application, which should allow me to experiment with what I want to do.

I like your suggestion that this issue could be cleared by just modifying the README to show how to compile C files without using CMake/Make...

Just a question about use of the library while here: While binding a JavaScript function that calls a C/C++ works as per the examples and tests, and while I can find examples in the tests of webview_eval being used to call these bindings as methods of the window, I can't find any examples of using webview_eval to call JavaScript in the context of the HTML in the window. In other words, while one can sent encoded information as a string from the webview window HTML to C/C++ code through use of a bind function, I don't see any examples of modifying the HTML DOM by calling JavaScript code from C/C++ code other than be using webview_set_html which would seem to be inefficient in requiring the entire HTML window be parsed and rendered when all one might want to do is change a single attribute or text string.

Perhaps I am missing something (as usual) but any suggestions would be most appreciated...

@SteffenL
Copy link
Collaborator

SteffenL commented Dec 5, 2024

Example code for webview_eval would be good. I came up with this possibly clumsy example for you.

#include "webview/webview.h"
#include <stddef.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#endif

void add_message(webview_t w, const char *message) {
  char script[256] = {0};
  strcat(script, "(() => {\n"
                 "  const el = document.createElement('div');\n"
                 "  el.textContent = '");
  strcat(script, message); // Warning: Not escaped
  strcat(script, "';\n"
                 "  messages.appendChild(el);\n"
                 "})()");
  webview_eval(w, script);
}

void on_page_init(const char *id, const char *req, void *user_data) {
  webview_t w = (webview_t)user_data;
  webview_return(w, id, 0, "");
  add_message(w, "Message #1");
  add_message(w, "Message #2");
  add_message(w, "Message #3");
}

#ifdef _WIN32
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine,
                   int nCmdShow) {
  (void)hInst;
  (void)hPrevInst;
  (void)lpCmdLine;
  (void)nCmdShow;
#else
int main(void) {
#endif
  webview_t w = webview_create(1, NULL);
  webview_set_title(w, "Basic Example");
  webview_set_size(w, 480, 320, WEBVIEW_HINT_NONE);
  webview_bind(w, "on_page_init", on_page_init, w);
  webview_init(w, "on_page_init()");
  webview_set_html(w, "<div id=\"messages\"></div>");
  webview_run(w);
  webview_destroy(w);
  return 0;
}

This should give you a window that looks similar to this:
image

@GordonBGood
Copy link
Author

@SteffenL,

Your example was very useful, although I was gradually getting there myself; the thing I was missing is that the webview_eval needs to be called from when the run/event loop is running, so a little bit of hook-up needs to be done to ensure this. My perhaps even simpler example of using this just to toggle the background colour of a button every time it is clicked is as in the following code (in C):

#include <stdio.h>
#include <stdlib.h>
#include "webview.h"

#ifdef _WIN32
#include <windows.h>
#endif

typedef struct {
  webview_t w;
  int state;
} arg_t;

void myFunc(const char *id, const char *req, void *arg) {
  printf("Params: %s\n", req);
  arg_t *strctp = (arg_t *)arg;
  webview_t w = (webview_t)strctp->w;
  if (strctp->state) {
    strctp->state = 0;
//    webview_set_html(w, "<button onclick='myFunc(\"Foo bar\")' style='background-color:red;'>Click Me...</button>");
    webview_eval(w, "window.document.body.firstElementChild.setAttribute('style', 'background-color:red;');");
  } else {
    strctp->state = 1;
//    webview_set_html(w, "<button onclick='myFunc(\"Foo bar\")' style='background-color:green;'>Click Me...</button>");
    webview_eval(w, "window.document.body.firstElementChild.setAttribute('style', 'background-color:green;');");
  }
}

#ifdef WIN32
int WINAPI WinMain(HINSTANCE hInt, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) {
#else
int main() {
#endif
  webview_t w = webview_create(0, NULL);
  arg_t arg = { .w = w, .state = 0 };
  webview_set_title(w, "Webview Example");
  webview_set_size(w, 480, 320, WEBVIEW_HINT_NONE);
  webview_bind(w, "myFunc", myFunc, &arg);
  webview_set_html(w, "<button onclick='myFunc(window.document.body.firstElementChild.getAttribute(\"style\"))' style='background-color:red;'>Click to Toggle...</button>");
  webview_run(w);
  webview_destroy(w);
  return 0;
}

I left in the printf to confirm that the style attribute is being toggled, and also the commented out webview_set_html statements that show the slow way to get this done, especially if the page is quite complex with a lot of nested elements and attributes (unlike this one)...

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

No branches or pull requests

2 participants