Hi,
A couple of month back I tried to make the webview work for Nim against the new version. (https://github.com/webview/webview) The implementation link on the page use the old version, which is buggy and terribly slow, and is not upgradable.
I had the basic working fine, but now if I want to be able to continue my project using Nim, I need to have the webview_dispatch and webview_bind working. The trouble is, it a bit out of reach of my elementary knowledge of C/C++.
Here is the bind function. https://github.com/francisl/webview/blob/add_bind_proc/webview/webview.h#L98
WEBVIEW_API void webview_bind(webview_t w, const char *name,
void (*fn)(const char *seq, const char *req,
void *arg),
void *arg);
Here is what I added in the Nim binding: https://github.com/francisl/webview/blob/add_bind_proc/webview.nim#L35
proc connect*(w:Webview, name:cstring, fn:pointer, arg:pointer){.importc:"webview_bind", header:"webview.h".}
...
var bindCallTable = newTable[int, BindFn]()
proc bindCProc(sequ:cstring, req:cstring, arg: pointer) {.exportc.} =
let idx = cast[int](arg)
let fn = bindCallTable[idx]
fn(sequ, req)
proc connect*(w: Webview, name: cstring, fn: BindFn) =
let idx = bindCallTable.len()+1
bindCallTable[idx] = fn
connect(w, name, bindCProc, cast[pointer](idx))
I don't really understand in the code what is a void *arg. It's a pointer of anything? What is it purpose? To get a little bit further, I based the code on the implementation of dispatch in the original Nim binding. From what I understand, the void *arg reference the 'mapped' callback. In that case, it retrieve the proc and in execute it in bindCProc.
Then I build an example to test that out. https://github.com/francisl/webview/blob/add_bind_proc/examples/minimal/minimal.nim#L3
But it fails when it tries to compile the C++ code:
.cache/nim/minimal_d/@m..@[email protected]:408:2: error: no matching function for call to 'webview_bind'
webview_bind(w, name, ((void*) (bindCProc)), ((void*) (idx)));
webview/webview/webview.h:1350:18: note: candidate function not viable: cannot convert argument of incomplete type 'void *' to 'void (*)(const char *, const char *, void *)' for 3rd argument
WEBVIEW_API void webview_bind(webview_t w, const char *name,
^
1 error generated.
What I understand from that, is the bindCProc passed to the connected proc, doesn't map correctly. But I don't get why, the test proc map the BindFn type definition.
If someone can point me in the right direction to learn and solve that, it would be appreciated.
Thank you
the void* arg is for the user callback to be able to take an argument. it's void* so it can be of any type.
the void* arg is for the user callback to be able to receive a parameter, it's void* so it can be any type, the user callback then casts it to the type it needs
you're getting an error because you've defined your wrapper for webview_bind incorrectly, it should be:
type WebviewCb = proc(seq: cstring, req: cstring, arg: pointer){.cdecl.}
proc connect*(w: Webview, name: cstring, fn: WebviewCb, arg: pointer){.importc:"webview_bind", header:"webview.h".}
i also managed to get your example to compile with the c backend, it's an utter hack and of dubious use. but hey:
in the config file define:
gcc.exe = "g++"
gcc.linkerexe = "g++"
-passC:-fpermissive #to allow converting char* to const char*
and change the header file to shut the linker up about the multiple definitions:
...
#define WEBVIEW_API extern __attribute__((weak))
...
Thanks for the answer.
Sadly I can't get that compiled either.
/webview/examples/minimal/minimal.nim(12, 2) Error: type mismatch: got <Webview, string, proc (seq: cstring, req: cstring, arg: pointer){.gcsafe, locks: 0.}>
but expected one of:
proc connect(w: Webview; name: cstring; fn: WebviewCb)
first type mismatch at position: 3
required type for fn: WebviewCb
but expression 'test' is of type: proc (seq: cstring, req: cstring, arg: pointer){.gcsafe, locks: 0.}
proc connect(w: Webview; name: cstring; fn: WebviewCb; arg: pointer)
first type mismatch at position: 3
required type for fn: WebviewCb
but expression 'test' is of type: proc (seq: cstring, req: cstring, arg: pointer){.gcsafe, locks: 0.}
expression: connect(w, "trythis", test)
The only thing I can get from that, is the compiler can see both as the same type. But I'm not sure why. I'll step back and try to read a bit more, I feel like I just shooting code in hope it will work ;-(
About the C compilation, what would be the benefits of doing that?
Have you taken a look at https://github.com/AS400JPLPC/nim_webwsi ? I believe it is based on webview as well
It was announced in a forum thread https://forum.nim-lang.org/t/7774#49407
ah yes you also need to define your bindCproc to match the WebviewCb type, i should have mentioned
proc bindCProc(sequ:cstring, req:cstring, arg: pointer) {.exportc,cdecl.} =
let idx = cast[int](arg)
...
theres no benefit to using the c backend i was just playing around.
Thank for the answers.
Sadly I'm still stuck with another error. Trouble for me, is my lack of understanding of C/C++ is dragging me down. TBH, I can't really comment on the error message. How I read it, I just don't understand why it can't match the function.
For example, with the current change it's NCSTRING instead of char. I never saw the code emit const char * only char *
webview/webview/webview.h:1350:18: note: candidate function not viable: no known conversion from 'void (NCSTRING, NCSTRING, void *)' (aka 'void (char *, char *, void *)') to
'void (*)(const char *, const char *, void *)' for 3rd argument
WEBVIEW_API void webview_bind(webview_t w, const char *name,
^
1 error generated.
Maybe my best next step is to try to do the project in C++ first and then try again finish the binding.
Hello, interesting your return. I had two goals the first was to make a real connection with webview.h and how to work it as well as the communication with Nim. It taught me a lot, on the other hand you must have seen that I only took into account Linux and I took the option of having three separate sessions. As for performance, it is also linked to your type of machine. Now I will see as soon as I have a moment to modify the CSS injection that I had found simple to initialize the context of the page.
Talk to you, also to have a native option instead of GTK (maybe I have translated incorrectly) GTK is on all platforms if you want to program with NIM with GINTRO you should not have any problem . Here for the case of making an association with webkit and in a way making a lib to replace the traditional browser, I don't think we need to reinvent the wheel, in my opinion ... I posted this as a template and to give ideas to those who might be interested ... and do more etc ... and not as a fundamental lib, but I take your remark as very thorough and have a closer look for rectify see lighten lib.
Thank you for the answer.
I removed the option inject css and set_font, this is done directly in the html page. on the other hand i process json in Nim main program.
The Json aspect is only useful to me to communicate data, so what Nim does it well ... and not in C as in your example. (Afterwards, it's a matter of taste, the less I touch the base the better I am) The page load time is less than a second. @soon
Coincidentally, I've been working on something similar lately in a PR.
Have a look if you want: https://github.com/arturo-lang/arturo/pull/275
Maybe that changed, but gtk was never a really good cross platform library. Look and feel, breaking keyboard defaults etc.
The original webkit.h already handle the use of the right windowing depending of the platform : https://github.com/webview/webview/blob/master/webview.h#L428
You can see it check for Linux GTK, Mac and then Windows to use the native UI libraries of the platform.
I not sure what is your goals are, but mine was to build something similar to wails (http://wails.app) It's a electron alternative were you don't need to bundle a browser + node. So it has better OS integration, faster loading time, faster execution (backend in go), smaller download size, massive memory use reduction. Plus you have the benefit of reusing your UI code, your expertise to build mobile (nativescript or react native), web and desktop.
As for the webview.h, inject_css was just an example, there was a lot of changes in their code. So if you don't update, there is not really a point to remove inject_css. In fact, I believe the wails team just update the webview.h and keep those.
You can see https://github.com/webview/webview/blob/master/README.md#migrating-from-v011-to-v0100
Anyway, now I have linker issue, my knowledge of compiled language can't make me far enough. I was able to get going with wails in 10 minutes last night, so I'll use it to my experiment for the moment.
So I'll declare forfeit for the time being, and come back to it when I have more time learn. At least it's closer to something usable than it was. Thank you
Thanks, merged it and its working perfectly.
where did you get the skills needed? Did you previously work in C/C++?