bye-Tyrael / chromiumembedded

Automatically exported from code.google.com/p/chromiumembedded
0 stars 1 forks source link

Need to build as Dll library. #1

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Linking with such huge static library lasts for ages. Linking with tiny 
lib, provided by Dll should speed up client builds a lot.

Original issue reported on code.google.com by vrid...@gmail.com on 10 Jan 2009 at 4:33

GoogleCodeExporter commented 9 years ago
A DLL build option is coming in the near future.

Original comment by magreenb...@gmail.com on 14 Jan 2009 at 8:08

GoogleCodeExporter commented 9 years ago
I already made it for my own, can send you diffs.

Original comment by vrid...@gmail.com on 15 Jan 2009 at 7:59

GoogleCodeExporter commented 9 years ago
Diffs are always welcome.  Please add them as a file attachment to this issue 
:-).

Original comment by magreenb...@gmail.com on 15 Jan 2009 at 2:33

GoogleCodeExporter commented 9 years ago
Here they are.

Original comment by vrid...@gmail.com on 15 Jan 2009 at 2:52

Attachments:

GoogleCodeExporter commented 9 years ago
Please also add a line to the AUTHORS.txt file so that I can credit you 
properly.

Original comment by magreenb...@gmail.com on 15 Jan 2009 at 3:06

GoogleCodeExporter commented 9 years ago
With VS2005 I get heap corruption in destructors of objects passed across the 
DLL
boundary.  This is because both libcef and cefclient are currently built using 
/MTd
(Multi-Threaded Debug), which results in the DLL and the EXE having separate 
heap
memory regions.  I've been unable to build libcef using /MTd (Multi-Threaded 
Debug
DLL) due to compile errors. If both libcef and cefclient were built using /MTd 
it
would resolve the heap corruption issue because they would both be sharing the 
heap
provided by the external runtime.

Problems with objects being allocated/deallocated across the DLL boundary are
primarily related to the use of standard library types.  Currently, we use
std::wstring as the return value for a number of methods.  Returning a 
std::wstring
results in the memory being allocated in the DLL and freed in the client 
application,
which causes the heap error.  Similarly, if we passed the std::wstring as an 
argument
by reference into the DLL the resizing (free/reallocate) would still take place 
in
the DLL, again resulting in the heap error. This leaves us with three options:

1. Avoid passing or returning standard library objects across the DLL boundary 
if
those objects will be modified. For instance, have the client pass in a wchar_t*
buffer instead of returning a std::wstring object.
2. Have the client application provide an allocator that would be used in the
creation or modification of any standard library objects passed across the DLL 
boundary.
3. Create our own versions/extensions of the standard library types that handle
memory allocation correctly and use those instead of the standard library types.

Original comment by magreenb...@gmail.com on 15 Jan 2009 at 5:43

GoogleCodeExporter commented 9 years ago
> With VS2005 I get heap corruption in destructors of objects passed across the 
DLL
boundary.  This is because both libcef and cefclient are currently built using 
/MTd
(Multi-Threaded Debug), which results in the DLL and the EXE having separate 
heap
memory regions.  I've been unable to build libcef using /MTd (Multi-Threaded 
Debug
DLL) due to compile errors. If both libcef and cefclient were built using /MTd 
it
would resolve the heap corruption issue because they would both be sharing the 
heap
provided by the external runtime.

Problem is not connected to different /M flags. WebKit use FastAlloc, and this 
is 
incompetible with standard allocator. See USE_SYSTEM_MALLOC define and 
FastAlloc.h/.cpp

Original comment by vrid...@gmail.com on 15 Jan 2009 at 6:07

GoogleCodeExporter commented 9 years ago
Anycase, passing string/wstring or other STL container through Dll boundaries 
is a 
bad idea. Now I'm looking for quick replacement for it

Original comment by vrid...@gmail.com on 15 Jan 2009 at 6:14

GoogleCodeExporter commented 9 years ago
I've found quick'n'dirty solution, see attached patch. Of course I don't like 
it - 
overriding of global new/delete operators is a bad idea, as for me. Also, using 
dllexport functions for new/delete will affect performance.

Ideally, the best solution (at least, for me ;) ) will be pure C interface, 
exported 
from libcef.dll, probably, with C++ wrappers around it. Pure C interface will 
avoid 
problems like we've ran into, and also can be easy integrated with .Net/Java 
and even  
Visual Basic. From the other side, C++ wrappers will allow easy integrate CEF 
into 
existing C++ projects.

Original comment by vrid...@gmail.com on 16 Jan 2009 at 8:30

Attachments:

GoogleCodeExporter commented 9 years ago
My current plan is a C interface with a separate, optional, C++ wrapper.  I will
probably keep the existing libcef as a static library (renamed to libcef_s), and
create a new libcef library that links against libcef_s and exports the C 
interface.
Here are the highlights for the proposed C API that I'm currently working on:

1. Move all struct/enum definitions out of cef.h into a separate header.  
Definitions
will follow standard C naming conventions ('_t' for typedef'd values, macros in
capitals, function names all in lower case with underscores, etc). Aliases to 
camel
case will be provided for structs/enums used by the existing C++ API.

2. Provide structure definitions with a 1:1 relationship to Cef objects and that
maintain the reference counting concept:

typedef struct _cef_base_t
{
  size_t size;  // structure size, used for backwards/forwards version compatibility
  int type;     // object type, #ifdef'd values
  void* ptr;    // opaque implementation pointer

  int (CEF_CALLBACK *add_ref)(cef_base_t* base);
  int (CEF_CALLBACK *release)(cef_base_t* base);
} cef_base_t;

typedef struct _cef_browser_t
{
  cef_base_t base;

  bool_t (CEF_CALLBACK *can_go_back)(cef_browser_t* browser);
  // And so on
} cef_browser_t;

3. All new methods will be added at the end of existing structures to maintain 
binary
compatibility between versions.

4. All strings will be null-terminated wchar_t*.  Strings will be returned via
wchar_t* buffers provided by the calling code.

cef_browser_t *myBrowser = ...;
size_t length;
wchar_t *buff;

// Retrieve the length of the URL, not including the NULL terminator.
myBrowser->get_url_length(&length);

// Allocate a buffer with enough space for the URL including the NULL 
terminator.
buff = (wchar_t*)malloc(sizeof(wchar_t) * (length+1));

// Read the URL into the buffer. If the buffer is too short the string will
// be truncated. A NULL terminator will always be added at the end of the 
string.
myBrowser->get_url(buff, length);

// Print the URL.
wprintf(L"url is %s", buff);

// Free the buffer.
free(buff);

5. Provide C-style functions for existing C++ static methods:

bool_t CEF_EXPORT cef_create_browser(cef_window_info_t* window_info, bool_t 
popup,
                                     cef_handler_t* handler, wchar_t* url)

6. Provide a static C++ library with Cef class wrappers calling the C API 
exported by
libcef.  The wrappers will match the C++ API exactly to allow transparent 
switching
between static and dynamic builds of libcef.

Original comment by magreenb...@gmail.com on 16 Jan 2009 at 3:44

GoogleCodeExporter commented 9 years ago
Looks good for me.
Just some ideas:

I'd rather have a following base structure:

typedef struct _cef_base_t
{
  int (CEF_CALLBACK *add_ref)(cef_base_t* base);
  int (CEF_CALLBACK *release)(cef_base_t* base);
} cef_base_t;

All memory will be freed by "release" function, so we do not need to have 
neither 
size, nor pointer to implementation. Let's have COM or XPCOM in mind to see how 
create OO-programs for pure C ;)

Also, to work with string - I think it will be better to have couple of 
functions in 
API like alloc_string(wchar_t*)/free_string(wchar_t*) and pass all strings 
through 
them. It also very close to COM BSTR implementation.

Original comment by vrid...@gmail.com on 16 Jan 2009 at 5:14

GoogleCodeExporter commented 9 years ago
A. I agree that we could do away with the implementation pointer by using nested
structures and type casting:

struct my_browser_t
{
  cef_browser_t browser;
  ...
};

cef_browser_t* browser = ...;
struct my_browser_t* mybrowser = (struct my_browser_t*)browser;

However, I'm not a big fan of creating a new structure (or class) every time we 
need
to add a new member function, which is the versioning system used by COM.  I 
would
prefer something like the WinAPI where the size member of the structure tells 
us what
members it will contain.  This allows us both backwards and forwards 
compatibility
with the same data structures (as long as we always add new members at the end 
of the
structure, and don't get too carried away with using nested structures to 
simulate
inheritance).  Of course, we will have to make it clear that the size member is 
the
size of the nested CEF API structure as defined in the CEF header, not the size 
of
the wrapping implementation structure.

On the subject of strings, the only objection I have to an API like COM BSTR is 
the
level of complexity it could add for the user.  But then, allocating and 
managing
buffers isn't very pretty either, so I'll explore your suggestion and see where 
it
takes me.

Original comment by magreenb...@gmail.com on 16 Jan 2009 at 6:22

GoogleCodeExporter commented 9 years ago
Yet another patch - I've added "ExecuteJavascript" method to Browser interface.

Original comment by vrid...@gmail.com on 17 Jan 2009 at 4:07

Attachments:

GoogleCodeExporter commented 9 years ago
The ExecuteJavascript method should accept a TargetFrame parameter so that 
either the
main frame or the focused frame can be targetted.

Original comment by magreenb...@gmail.com on 21 Jan 2009 at 4:10

GoogleCodeExporter commented 9 years ago
I already made it, there is updated path.
I also added some handlers to catch some additional events in Handler - popup 
window 
show and popup window close.

By the way, may be you know - is it possible to run CEF/Chromium in my own 
message 
loop? In most cases having 2 message loops is a cause of problems.

Original comment by vrid...@gmail.com on 21 Jan 2009 at 4:20

Attachments:

GoogleCodeExporter commented 9 years ago
What kind of problems are you having?

Original comment by magreenb...@gmail.com on 21 Jan 2009 at 4:30

GoogleCodeExporter commented 9 years ago
Deadlocks in most cases.

CEF calls Handler methods in it's UI thread, but I need to pass it's call into 
my 
framework thread. I use something like SendMessage for this. In this case, CEF 
thread 
is locked until my component returns. If my component opens additional windows 
in 
this handler, these windows waits for redraw from Chromium. But as far as CEF 
thread 
is locked, I got a deadlock there.

Original comment by vrid...@gmail.com on 21 Jan 2009 at 4:36

GoogleCodeExporter commented 9 years ago
You should use PostMessage(), which is the thread-safe non-blocking form of
SendMessage(). If you need the multi-threaded communication to block then you 
should
use events as demonstrated by the CefBrowserImpl::GetSource() method in
browser_impl_win.cc.  We may also need to expose a version of the PostTask() 
function
in the future so that CEF users can specify code for execution on the UI thread.

Original comment by magreenb...@gmail.com on 21 Jan 2009 at 4:49

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Look at Handler.HandleBeforeCreated, for example.
My code should run actual workers in another message thread (let's call it 
Appframework message thread), to be thread-consistence with this framework. 
From the 
other side, this worker should return some decision - shell I allow popup to 
appear 
or not. So, I can not allow CEF message loop to run until my worker (in 
Appframework 
thread!) finished it's work. From the other case, if this worker creates some 
windows 
that requires Chromium windows redrawing, we've got a deadlock.

Original comment by vrid...@gmail.com on 21 Jan 2009 at 5:08

GoogleCodeExporter commented 9 years ago
Blocking the UI thread in this case probably isn't a good idea.  What you can 
do is
cancel the new window creation (return RV_HANDLED from HandleBeforeCreated) and 
then,
after your processing is complete, call CreateBrowser() with the parameters
originally passed to HandleBeforeCreated.  This might be problematic, however, 
if you
have JavaScript that assumes the existence of the new window.

Original comment by magreenb...@gmail.com on 21 Jan 2009 at 5:17

GoogleCodeExporter commented 9 years ago
> This might be problematic, however, if you have JavaScript that assumes the 
existence of the new window.

Exactly.
I'm trying to substitute MessageLoopForUI to workaround this now.
I will report you about results.

Original comment by vrid...@gmail.com on 21 Jan 2009 at 5:29

GoogleCodeExporter commented 9 years ago
You might also try modifying the JavaScript so that either (a) it polls for the 
new
window to exist or (b) the container executes a JavaScript call after the 
window is
created to continue the JavaScript execution.

Original comment by magreenb...@gmail.com on 21 Jan 2009 at 5:39

GoogleCodeExporter commented 9 years ago
It seems I've got some results. There is a diff file to show the main idea (not 
a 
final patch, of course). At least, cefclient seems to work with this issue in 
the 
single message loop.

Original comment by vrid...@gmail.com on 21 Jan 2009 at 7:20

Attachments:

GoogleCodeExporter commented 9 years ago
There is final patch for running Chromium UI in my own message loop. Looking 
forward 
for your comments ;)

Original comment by vrid...@gmail.com on 22 Jan 2009 at 4:40

Attachments:

GoogleCodeExporter commented 9 years ago
By the way, if we are removing extra message loop, we can change 
Browser::CreateBrowser to allow it to return Browser instance. 

This will simplify an API - it much simple for user to get ready-to-use Browser 
instance from a factory method instead of waiting for it in the handler (for 
some 
simplest cases user will not be forced to create Handler at all).

What do you think of this idea?

Original comment by vrid...@gmail.com on 23 Jan 2009 at 1:20

GoogleCodeExporter commented 9 years ago
I haven't had a chance to test it yet, but your concept of running chromium UI 
in the
current thread's message loop looks OK.  In your modified version of cefclient, 
when
do you call CefDoMessageLoopWork()?

I agree that if we remove the extra message loop we could return the CefBrowser
instance directly from CefBrowser::CreateBrowser().

If we move to a single message loop then we could actually make all of CEF
single-threaded.  The code simplification gains might not be worth the loss of
multi-threaded support, though.

Original comment by magreenb...@gmail.com on 23 Jan 2009 at 3:09

GoogleCodeExporter commented 9 years ago
> In your modified version of cefclient, when do you call 
CefDoMessageLoopWork()?
Just inside message loop:

    // Main message loop
    while (GetMessage(&msg, NULL, 0, 0))
    {
        CefDoMessageLoopWork();

        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

Original comment by vrid...@gmail.com on 23 Jan 2009 at 4:17

GoogleCodeExporter commented 9 years ago
Patch for solution with running in a single message loop

Original comment by vrid...@gmail.com on 28 Jan 2009 at 10:03

Attachments:

GoogleCodeExporter commented 9 years ago
What do you use the HandleBeforeWindowShow(), HandleAfterWindowShow() and
HandleBeforeWindowClose() notifications for?

Original comment by magreenb...@gmail.com on 29 Jan 2009 at 5:53

GoogleCodeExporter commented 9 years ago
rev 12 adds CefBrowser::ExecuteJavaScript() and rev 13 adds single-threaded 
message
loop support.

Original comment by magreenb...@gmail.com on 29 Jan 2009 at 6:54

GoogleCodeExporter commented 9 years ago
> What do you use the HandleBeforeWindowShow(), HandleAfterWindowShow() and
HandleBeforeWindowClose() notifications for?

They are supposed to be used as a notifications for opening/showing popup 
windows (IE 
has similar one). But it's not a final version, I will send you updated diff 
when 
they will be ready (I think it will be in a day or two).

Original comment by vrid...@gmail.com on 29 Jan 2009 at 7:03

GoogleCodeExporter commented 9 years ago
Hi all!
i'm not a c++ programmer ( unfortunately :( ) , but i want try to use a 
chromium in 
my project on delphi. so at this point i need to create dynamic library with 
chromium inside and minimum exported functions that can create, destroy, 
navigate 
(at least url in creation time ) chromium instance. all what i need - just a 
windows 
handle of this instance .
i look on this project - wow - it's a magic ((c) David Blein) - that is what i 
need.
(thanks a lot for magreenblatt, and for all who make this project better ).

i tried to build rev 10 - it's was builded successfully, cefclient is work.
after that i try to build last (15 ) revision -  there is some problems with 
build ( 
i think that problem in a chrome revision (from compability list ) or  
in my hands 8-( 
Now main question - anybody can help me  to make  a dynamic library with 
functionality like a cefclient - because when i tried to make it ( 
i create new empty library (another one project in chromiumembedded), declare 3 
export functions to test (
extern CEFDLL_API bool CefInitialize(bool multi_threaded_message_loop);
extern CEFDLL_API void CefShutdown();
extern CEFDLL_API void CefDoMessageLoopWork();
), write include cefclient.h, cef.h
but project did'nt builded - cef.h not found :(

help me please with writing this simple dll or finish this issue - it is much 
better  :)
with best regards to all those involved in this project,
 Alexander  

Original comment by azy...@gmail.com on 26 Feb 2009 at 9:14

GoogleCodeExporter commented 9 years ago
Rev 16 adds DLL build support. Feedback and testing is welcome :-).

Original comment by magreenb...@gmail.com on 5 Mar 2009 at 1:12

GoogleCodeExporter commented 9 years ago
The project does not open with Chromium revision trunk@9652 declared in 
CHROMIUM_BUILD_COMPATIBILITY.txt 

Original comment by azy...@gmail.com on 5 Mar 2009 at 12:08

GoogleCodeExporter commented 9 years ago
What project does not open?  What error message do you get?

Original comment by magreenb...@gmail.com on 5 Mar 2009 at 2:30

GoogleCodeExporter commented 9 years ago

Cannot open include file: 'ScriptState.h' and 'ScriptInstance.h'

Original comment by peng.che...@gmail.com on 5 Mar 2009 at 4:51

GoogleCodeExporter commented 9 years ago
You were probably not at the correct revision of chromium as set up by gclient 
sync.
 In any case, update to rev 17, which will fix your include problem.

Original comment by magreenb...@gmail.com on 5 Mar 2009 at 5:17

GoogleCodeExporter commented 9 years ago
Release build is broken in rev 19, I attached a patch to fix it.

Original comment by vrid...@gmail.com on 8 Mar 2009 at 10:32

Attachments:

GoogleCodeExporter commented 9 years ago
Sorry, previous patch is not complete
There is a correct one

Original comment by vrid...@gmail.com on 8 Mar 2009 at 10:34

Attachments:

GoogleCodeExporter commented 9 years ago
Thanks for the patch. Release build compile error fixed in rev 20.

Original comment by magreenb...@gmail.com on 9 Mar 2009 at 1:23

GoogleCodeExporter commented 9 years ago

Original comment by magreenb...@gmail.com on 17 Sep 2009 at 6:41