|
Hello,
I think Nishant Sivakumar's book "C++\CLI in action" talks about this specific topic in "6.6 Using an MFC control in a Windows Forms form" titled chapter.
I've not tried yet... but i hope this helps.
|
|
|
|
|
I have callback[delegate] in managed code being called by native code. It works fine the first time but on the next call the native code blows up. Bear with me the structure is a little twisted, but I'll try my best to explain.
Here's the general structure:
Client
|
--->ServiceInterface
|
--->NativeService
The main question is how should I be passing the callback to the native code from the ServiceInterface initialization?.
Should the delegate be pinned before passing it to the native code?
The following is not exact code but a snapshot of how the code is interacting.
// Managed code
#include "ServiceInterface.h"
ref class Client
{
public:
ServiceInterface ^mngService;
Client()
{
mngService = gcnew ServiceInterface(this);
}
void initialize()
{...}
void Task1()
{
mngService->registerCallback(Task1_Callback);
}
void Task2()
{
mngService->registerCallback(Task2_Callback);
}
static int Task1_Callback(void *pdata, MessageType event)
{
Console::WriteLine(L"Task 1 completed...");
// cast and remove listener for task 1
return 1;
}
static int Task2_Callback(void *pdata, MessageType event)
{
Console::WriteLine(L"Task 2 completed...");
// cast and remove listener for task 2
return 2;
}
};
// ServiceInterface.h
#include <nativecode.h>
public delegate int Callbackfunction(void *pdata, MessageType event);
ref class ServiceInterface
{
private:
static list<Callbackfunction> callbacklist;
NativeService *service;
static Callbackfunction ^MessageProcessor;
static GCHandle ghMasterCallback;
static IntPtr ipMasterCallback;
ServiceInterface(Object ^client)
{
service = new NativeService();
//// Thought this was the way to pass function pointer to native code,
//// but crashed on the first callback.
//MessageProcessor= gcnew Callbackfunction(&Service::MessageEngine);
//ghMasterCallback = GCHandle::Alloc(MessageProcessor);
//ipMasterCallback = Marshal::GetFunctionPointerForDelegate(MessageProcessor);
//service->RegisterEventProcessor((Callbackfunction)ipMasterCallback.ToPointer(), client(Void * Value));
// Instead this method seem to work, at least for the first callback but dies on the second callback[Task 2]
service->RegisterEventProcessor((Callbackfunction)&MessageEngine, client(Void * Value));
callbacklist = new list<Callbackfunction>;
}
void registerCallback(Callbackfunction ^callback)
{
callbacklist->push_back(callback);
}
void removeCallback(Callbackfunction ^callback)
{ // removes the given callback function}
// Registered as EventProcessor with NativeCode
// Calls delegates in managed code
int MessageEngine(void *pdata, MessageType event)
{
list <Callbackfunction>::iterator Iter;
for ( Iter = callbacklist.begin( ); Iter != callbacklist.end( ); Iter++ )
static_cast<Callbackfunction>(*Iter)(pdata,event);
}
};
// UNManaged code
// nativecode.h
enum MessageType
{
EVENT_START,...
};
typedef int (* Callbackfunction)(void *pdata, MessageType event);
class NativeService
{
private:
void *clientContext;
public:
NativeService(){...}
Initialize(){...}
// Callback function to be defined in managed interface
Callbackfunction EventProcessor;
DoWorkFunction
{
:
:
// Message generated from service
MessageType newMessage;
DispatchCallback(EventProcessor(clientContext, newMessage));
}
RegisterEventProcessor(Callbackfunction processor, void * client)
{
EventProcessor = processor;
clientContext = client;
}
};
|
|
|
|
|
Hi,
I did not study your code in detail, but I remember from earlier work the most probable
cause for a "works one time then bombs" situation is a mismatch in the calling conventions
(stdcall, CDecl, that kind of stuff). When calling from managed to unmanaged, you
can choose on both sides and of course you must choose the same on both sides; when
calling from unmanaged to managed, the managed side is fixed, and you must add the
right keywords to make the unmanaged side match the managed side.
Don't trust the defaults, look it up and use the correct calling convention explicitly.
[ADDED]
Another thing to keep in mind is the different sizes of some primitive data types;
among the most confusing are long (32bit unmanaged, 64bit managed) and char (8bit unmanaged,
16bit managed).
Also, if Win64 is relevant, make sure to pass all handles (as well as lParam and wParam)
as IntPtr, which takes either 32-bit or 64-bit depending on the platform.
[/ADDED]
Luc Pattyn [Forum Guidelines] [My Articles]
This month's tips:
- before you ask a question here, search CodeProject, then Google;
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get;
- use PRE tags to preserve formatting when showing multi-line code snippets.
modified on Wednesday, January 30, 2008 9:58:01 PM
|
|
|
|
|
Thanks for the feedback Luc. I'll double check those types, even though I doubt that's the root of the issue.
Thanks,
Jason
|
|
|
|
|
I am working on a winamp plugin in managed c++. i have another dll referenced in my project that i need to use (in C#). Everything compiles fine, however when the dll is loaded into winamp it throws a FileNotFoundException stating it can't load the C# dll. the dll is in the same directory as the c++/cli. what do i need to do to get the assembly detected?
thanks in advance,
Don't be overcome by evil, but overcome evil with good
|
|
|
|
|
teejayem wrote: FileNotFoundException
Post the exception message
led mike
|
|
|
|
|
Could not load file or assembly 'Facebook, Version=1.6.2951.20499, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Don't be overcome by evil, but overcome evil with good
|
|
|
|
|
teejayem wrote: it can't load the C# dll. the dll is in the same directory as the c++/cli. what do i need to do to get the assembly detected?
teejayem wrote: assembly 'Facebook, Version=1.6.2951.20499,
So the DLL is "Facebook.dll"? Does of the DLL match the one in the exception message?
teejayem wrote: I am working on a winamp plugin in managed c++.
Is the winamp interface to your DLL a native C++ interface? If so then there is probably some way (configuration data) to tell winamp where your DLL is right? So when the .NET runtime is loaded into the Winamp process, the .NET runtime doesn't know anything about the Winamp configuration data that points to the folder with those DLL's. The .NET runtime is using the current working folder of the Winamp process to look for that assembly, plus of course however else it looks for assemblies, but it certainly won't look in a folder that is only known to the Winamp native code.
led mike
|
|
|
|
|
yeah the facebook dll does match (version number and everything). you were right though, I put the facebook.dll in the directory where the executable lives (instead of the plugin directory where my plugin lives) and it worked perfectly! I always thought that the dependencies all had to be in the same folder (or else should be registered) and it had me totally messed up.
thank you so much!
Don't be overcome by evil, but overcome evil with good
|
|
|
|
|
Hi, all:
In VS2003, I had no problems declaring (custom control) properties that were visible in the properties window for the control - also in a catagory of my choosing (typically named after the control, itself).
With VS2008, I had to change the format for declaring the properties (to one much like that of C#). They compile without error, and can be used within the control class.
Problem is that they don't show in the properties window. Even if I use standard names. There also seems to be an insistance that I declare them as follows:
public:<br />
[Description("Some descriptive verbage"),Category("Layout"), Browsable(true)]
static property type propertyName {<br />
public: void set(type value) {...}<br />
public: type get() {....}<br />
}
The declaration as static has quite a few annoying side effects, and was unnecessary in the oldsyntax version (below).
This is not the first time I visited this problem, but now the frustration level is getting to me. How is this done correctly? I'd settle for, as above, where I have to use a predefine category, but would prefer to do as I'd done before, which is to block them together in a custom name.
Thanks, in advance,
Balboos
Old Syntax (VS2003):
<br />
public: <br />
[Description(S"Some Descriptive Verbage"),Category(S"Anything")]<br />
__property type get_PropertyName() { ... }<br />
__property void set_PropertyName(type value) { ... }
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"How do you find out if you're unwanted if everyone you try to ask tells you to go away?" - Balboos HaGadol
|
|
|
|
|
Never Mind - I finally Got it !
&U$A)U*$)P$*)P($ !!!!
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"How do you find out if you're unwanted if everyone you try to ask tells you to go away?" - Balboos HaGadol
|
|
|
|
|
...and what were you doing wrong or needed to change? This way the next person that runs in to the same problem has some ideas on what needs to be fixed.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
Fair Enough - The following will work, creating the properties and putting them in the specified category within the Properties Window for the control:
public:
[Description("Type A Description That Appears at Bottom of Prop Window"), Category("Some_Category")]
property type popertyName {
public: type get() { return dataMember;}
public: void set(type value) { dataMember = value; }
}
Now the above seems to be quite a simple change - the mess was that the early reference I found to this steered me in the direction of declaring the property static . All seemed well, although, being static, it require all of its members/called methods to be static objects, as well. This was not, for the general case, practical (and for inherited members, sanely do-able).
I figured out the error when I tried to use the property via 'hand coding': it would not let me use it as an instance, but only as a class member (because it was static - Duh!). This made me consider the static declaration not only a nusiance, but just plain wrong. Throwing caution to the wind, I deleted the (recommned via examples) static declaration and let the magic happen.
So trivial in hindsight. But why didn't the MSDN help just #*&)&&^)^ spell it out with a clear example?
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"How do you find out if you're unwanted if everyone you try to ask tells you to go away?" - Balboos HaGadol
|
|
|
|
|
Thanks. Now that the difference is clear, it does seem so trivial.
Balboos wrote: But why didn't the MSDN help just #*&)&&^)^ spell it out with a clear example?
You're joking, right? MSDN docs with clear examples? It'll never happen.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
Scott Dorman wrote: You're joking, right? MSDN docs with clear examples? It'll never happen
Either a rhetorical question or just being cynical.
When I was first learning managed C++, I was trying to find out how to use the ExecuteScaler() method from ADO.NET - I was having trouble figuring out how to cast the value in the new syntax. Foolishly got to the MSDN help, I found an example of ExecuteScale(), but they treated it like it had void for a return type (instead of Object * which was before the current Object ^ ). My initial instinct was to find out if homocide was illegal in Redmond, Washington.
Another rhetorical question, then: the people who have written the 'help' - are they sadists - or just plain stupid?
Yet . . . I keep ending up going back there . . . making me wonder about myself, or, to quote Forest Gump: "Stupid is as stupid does" ????
Thank the Great Coder In The Sky I only have half-a-day, today.
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
"How do you find out if you're unwanted if everyone you try to ask tells you to go away?" - Balboos HaGadol
|
|
|
|
|
Hi,
I want to give the XMLwrite::Create(...)
an URI format address...
because I want to save my file (e.g config file) in my http:// address. and I don't want to use Database...
If there is a way to do it(or other ways) please tell me
thank you.
Every new thing you learn,Gives you a new personality.
|
|
|
|
|
dSolariuM wrote: because I want to save my file (e.g config file) in my http:// address
HTTP doesn't work like that, you better do some studying. Software developers should understand the technologies they intend to use before planing how to use them, otherwise you end up trying to install a clutch in your refrigerator.
led mike
|
|
|
|
|
There are Mdi parent and its child form. In parent Mdi header file I include "child.h" in order to create and show it to the screen. But how to access from child any public data of Mdi parent. If I include in child.h "parent.h" it does not compile? cross reference.
parent.h file
#include "child.h"
class Parent {
...
}
child.h file
#include "parent.h" <------- does not allow to be compiled
class Child {
...
}
chesnokov
|
|
|
|
|
Look at Model-View-Control pattern[^], views should not be tightly coupled. One obvious approach to avoiding two classes being tightly coupled is to use a third.
classA classB
\ /
\ /
\ /
classC
led mike
|
|
|
|
|
|
The manifest may only be part of the problem, if at all.
You also have to ensure all required modules/assemblies/etc.
are available on the target machine.
Deployment (C++)[^]
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Thanks, but the problem was only solved when I used static linking instead of dynamic linking of multithreaded C library
ARSALAN MALIK
|
|
|
|
|