www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - problem with C dll

reply bobef <bobef_member pathlink.com> writes:
I'm trying to get a working browser in D app. It is works (extremely slow for
me) with core32 library but I could not figure out how to get notified about
events (onbeforenavigate, etc) with core32. So now I'm struggling with MFC.
I made a dll that does CHtmlView for me, but it does not work. After some time
in debuggin I found that the HWND I pass to the dll function is changed in the
process, so I tried with a char* and it gets changed too... I find that very
strange... any suggestions? Here is some code...

MFC:

extern "C" __declspec( dllexport ) void* create(char* f)
{
AfxMessageBox(f);
return 0;
/*htmlView *view=new htmlView;
if(view)
{
RECT r;
GetClientRect(f,&r);
CString a;
CWnd::FromHandle(f)->GetWindowText(a);
AfxMessageBox(a);
if(view->Create(0,0,WS_VISIBLE|WS_CHILD,r,CWnd::FromHandle(f),AFX_IDW_PANE_FIRST,0))
{
return view;
}
else
{
//delete view; //this one crashes
return 0;
}
}
return 0;*/
}

D:

HMODULE dll=LoadLibrary("browser.dll");
create=cast(void* function(char *))GetProcAddress(dll,"create");
destroy=cast(void function(void *))GetProcAddress(dll,"destroy");
//all good so far
create("tosho"); //and i get some strage symbols in the messagebox...
//if i try to display getwindowtext() it is empty although i've set one (and f
is HWND of course)...
Mar 16 2005
next sibling parent "John C" <johnch_atms hotmail.com> writes:
"bobef" <bobef_member pathlink.com> wrote in message 
news:d19c8a$1573$1 digitaldaemon.com...
 I'm trying to get a working browser in D app. It is works (extremely slow 
 for
 me) with core32 library but I could not figure out how to get notified 
 about
 events (onbeforenavigate, etc) with core32. So now I'm struggling with 
 MFC.

There's no reason why you shouldn't be able to get it all working in D. core32 doesn't declare IConnectionPoint and the related interfaces needed to attach event sinks. If you've got the SDK, they're in ocidl.h and are straightforward to translate into D. To receive events, you need to implement DWebBrowserEvents2/IDispatch (exdisp.h). This article from MSJ should give you some help http://www.microsoft.com/msj/0698/browser.aspx Specifically the section titled "Sinking events from C++". (If you've got the .NET 2.0 framework installed, fire up Reflector and peek inside the WebBrowser class, although it might be difficult to follow at first because C# hides all the COM QueryInterface stuff in ordinary casts.)
 I made a dll that does CHtmlView for me, but it does not work. After some 
 time
 in debuggin I found that the HWND I pass to the dll function is changed in 
 the
 process, so I tried with a char* and it gets changed too... I find that 
 very
 strange... any suggestions? Here is some code...

 MFC:

 extern "C" __declspec( dllexport ) void* create(char* f)
 {
 AfxMessageBox(f);
 return 0;
 /*htmlView *view=new htmlView;
 if(view)
 {
 RECT r;
 GetClientRect(f,&r);
 CString a;
 CWnd::FromHandle(f)->GetWindowText(a);
 AfxMessageBox(a);
 if(view->Create(0,0,WS_VISIBLE|WS_CHILD,r,CWnd::FromHandle(f),AFX_IDW_PANE_FIRST,0))
 {
 return view;
 }
 else
 {
 //delete view; //this one crashes
 return 0;
 }
 }
 return 0;*/
 }

 D:

 HMODULE dll=LoadLibrary("browser.dll");
 create=cast(void* function(char *))GetProcAddress(dll,"create");
 destroy=cast(void function(void *))GetProcAddress(dll,"destroy");
 //all good so far
 create("tosho"); //and i get some strage symbols in the messagebox...
 //if i try to display getwindowtext() it is empty although i've set one 
 (and f
 is HWND of course)...

 

Mar 16 2005
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 create=cast(void* function(char *))GetProcAddress(dll,"create");
 destroy=cast(void function(void *))GetProcAddress(dll,"destroy");

I think it has to do with throwing away the "extern(C)" in the cast. The following example shows a similar bad behavior that is fixed when the type of bar includes the extern(C). extern(C) void* foo(char* p) { printf("foo p %p\n",p); return p; } int main() { // uncomment next two lines to get it working // typeof(&foo) bar; // bar = &foo; // this is the bad version void* function(char*) bar; bar = cast(void* function(char*))&foo; char*p = new char; void* res; printf("before calling anything\n"); printf("p %p\n",p); printf("about to call foo directly\n"); res = foo(p); printf("res %p\n",res); printf("about to call bar\n"); res = bar(p); printf("res %p\n",res); return 0; }
Mar 16 2005
parent bobef <bobef_member pathlink.com> writes:
Yes it is. I learned this little trick from undig's scintilla conversation.
define function type as
extern (C) alias void *(*type)(char *);
then cast(type)getprocaddress and all goes smoothly...

In article <d19m9o$1h8i$1 digitaldaemon.com>, Ben Hinkle says...
 create=cast(void* function(char *))GetProcAddress(dll,"create");
 destroy=cast(void function(void *))GetProcAddress(dll,"destroy");

I think it has to do with throwing away the "extern(C)" in the cast. The following example shows a similar bad behavior that is fixed when the type of bar includes the extern(C). extern(C) void* foo(char* p) { printf("foo p %p\n",p); return p; } int main() { // uncomment next two lines to get it working // typeof(&foo) bar; // bar = &foo; // this is the bad version void* function(char*) bar; bar = cast(void* function(char*))&foo; char*p = new char; void* res; printf("before calling anything\n"); printf("p %p\n",p); printf("about to call foo directly\n"); res = foo(p); printf("res %p\n",res); printf("about to call bar\n"); res = bar(p); printf("res %p\n",res); return 0; }

Mar 16 2005
prev sibling next sibling parent "Charles" <cee-lo green.com> writes:
Good lord, MFC in D ?  How in the world did you manage this ??




"bobef" <bobef_member pathlink.com> wrote in message
news:d19c8a$1573$1 digitaldaemon.com...
 I'm trying to get a working browser in D app. It is works (extremely slow

 me) with core32 library but I could not figure out how to get notified

 events (onbeforenavigate, etc) with core32. So now I'm struggling with

 I made a dll that does CHtmlView for me, but it does not work. After some

 in debuggin I found that the HWND I pass to the dll function is changed in

 process, so I tried with a char* and it gets changed too... I find that

 strange... any suggestions? Here is some code...

 MFC:

 extern "C" __declspec( dllexport ) void* create(char* f)
 {
 AfxMessageBox(f);
 return 0;
 /*htmlView *view=new htmlView;
 if(view)
 {
 RECT r;
 GetClientRect(f,&r);
 CString a;
 CWnd::FromHandle(f)->GetWindowText(a);
 AfxMessageBox(a);

IRST,0))
 {
 return view;
 }
 else
 {
 //delete view; //this one crashes
 return 0;
 }
 }
 return 0;*/
 }

 D:

 HMODULE dll=LoadLibrary("browser.dll");
 create=cast(void* function(char *))GetProcAddress(dll,"create");
 destroy=cast(void function(void *))GetProcAddress(dll,"destroy");
 //all good so far
 create("tosho"); //and i get some strage symbols in the messagebox...
 //if i try to display getwindowtext() it is empty although i've set one

 is HWND of course)...

Mar 16 2005
prev sibling parent reply John Reimer <brk_6502 yahoo.com> writes:
bobef wrote:

 D:
 
 HMODULE dll=LoadLibrary("browser.dll");
 create=cast(void* function(char *))GetProcAddress(dll,"create");
 destroy=cast(void function(void *))GetProcAddress(dll,"destroy");

Like Ben said, this is probably the big part of the problem. "create" and "destroy" are assigned a function pointer, but that casted function pointer is extern(D) by default. In this case, it likely has to be extern(Windows). So create the variables like this: extern(C) void* function(char *) create; extern(C) void function(void *) destroy; This declaration must be done at module scope, however, because D currently doesn't recognize the "extern" attribute inside functions. If you wanted to make local function pointers, you could easily define a typedef or alias for them at module scope and then declare the variables inside the function with that type: extern(C) alias void* function(char*) FunctionTypeA; extern(C) alias void function(void*) FunctionTypeB; ... void main() { FunctionTypeA create; FunctionTypeB destroy; ... } The above method makes it easy to assign with the cast you intended. This time it should work because the "extern" type correctly matches the calling convention of the function returned by "GetProcAddress": ... create = cast(FunctionTypeA) GetProcAddress(dll, "create"); destroy = cast(FunctionTypeB) GetProcAddress(dll, "destroy"); ... Hope that helps, JJR
Mar 16 2005
parent John Reimer <brk_6502 yahoo.com> writes:
John Reimer wrote:

 
 Like Ben said, this is probably the big part of the problem.  "create" 
 and "destroy" are assigned a function pointer, but that casted function 
 pointer is extern(D) by default.  In this case, it likely has to be 
 extern(Windows).  So create the variables like this:
 

Sorry, I meant extern(C).
Mar 16 2005