Click here to Skip to main content
15,887,320 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a console application in C++ that when loaded load a library in C#, which, in turn, when loaded shows a modal form with several buttons.

I need to implement a call back function from C# to C++ to indicate, in the C++ console output, every time an action is made in the modal form.

When the C ++ application is executed, the form is not displayed and the application ends without an answer after a few seconds (15 mm).

If the section indicated as //Return call function statement is commented (on C# side), the application is executed and the form is displayed. This indicates that something is not declared as it should be on the C# side.

For me it is totally new to make C++ converge with C# during a modal function like that of the form.

I need to know how to correct the statement so that the callback function is recognized.

What I have tried:

I have corrected the code but when I run the callback function it gives me an ECall security error

I have treated the following code C++:

int wmain(int argc, _TCHAR* argv[]) {

if (hResult == S_OK) {
std::wcout << returned_thing << std::endl;
return 0;
}
return 1;
}


The previous application communicates with the library in C # with the following code C #:
C#
namespace CSharpClass
{
    public class The33Class
    {
        CPPCallBack _CPPCallBack = null;

        public void SetCallBacks(IntPtr cppCallBack)
        {
        }


        public String Getng(String arg) // Make sure this is public
        {
        }

    }
}
Posted
Updated 20-Nov-18 0:21am
v6
Comments
Richard MacCutchan 16-Nov-18 9:33am    
You could have solved this problem some time ago if you had used a proper C# main class to interface with the library.
fisadmaster 16-Nov-18 9:37am    
That is the reason that I am asking how to adjust the code, the original code is not mine, but it has been useful for me before making bridges. If you are so kind could you show me how to correct the statements?
Richard MacCutchan 16-Nov-18 11:12am    
Unmanaged C++ code does not fit well with .NET so I do not know how you could solve this. I can only suggest that you use Google to try and find a sample that someone has actually made to work.
Rick York 16-Nov-18 12:33pm    
If I were you I would need to have a VERY compelling reason to fight with this issue so much. So far, I have not read one from you but that's OK. You don't have to justify this to me. I would rewrite one of those two modules in the same language as the other and all of this complexity would be eliminated. You could probably have done a rewrite in the time you have spent fighting this and from all indications will likely continue to spend.
fisadmaster 17-Nov-18 11:07am    
I have corrected the code but when I run the callback function it gives me an ECall security error

I did similar things before some years. A very pragmatic Approach (and maybe also a very dirty one).
Keep in mind I noted here what I remember...

The c# part
public class CSharpCom
{
   // c++ Callback stuff
   private delegate void CPPCallBack([MarshalAs(UnmanagedType.BStr)] string text);

   CPPCallBack _CPPCallBack= null;

   // To set callback from c++ 
   public void SetCallBacks(IntPtr cppCallBack)
   {
      _CPPCallBack= (CPPCallBack)Marshal.GetDelegateForFunctionPointer(
                     cppCallBack,
                     typeof(CPPCallBack));
   }

   // Using of the callback
   public void LogMsg(string msg)
   {
      try
      {
          _CPPCallBack?.Invoke(msg);
      }
      catch
      {
         // Error handling
      }
   }


   // You other COM stuff
}


The c++ part
static void __stdcall CPPCallBack(BSTR msg)
{
  // Implement callback stuff here
}

int wmain(int argc, char* argv[])
{
	CoInitialize(0); // Init COM

	BSTR thing_to_send = ::SysAllocString(L"10 20");
	BSTR returned_thing;
	CSharpDll::_TheClassPtr obj(__uuidof(CSharpDll::TheClass));

        // Register the callback
        obj->SetCallBacks((INT64)CPPCallBack);

	HRESULT hResult = obj->GetTheThing(thing_to_send, &returned_thing);

	if (hResult == S_OK) {
		std::wcout << returned_thing << std::endl;
		return 0;
	}
	return 1;
}


I hope it helps

[Edit]
code adjusted according to OP's feedback
 
Share this answer
 
v5
Comments
fisadmaster 17-Nov-18 13:37pm    
Thanks for the code but the part,
_CPPCallBack = (CPPCallBack) .Marshal.GetDelegateForFunctionPointer (
                      cppCallBack,
                      typeof (CPPCallBack));

shows me the error: CSharpCom.CPPCallBack is a type which is not valid in the given context and CSharpCom.CPPCallBack does not contain a definition for 'Marshal'

I have included your code in the question so you can see the side of C # implemented
Any idea?
[no name] 17-Nov-18 13:46pm    
Ok, not sure but maybe the delegate Definition Needs to be public. Try this public delegate void CPPCallBack([MarshalAs(UnmanagedType.BStr)] string text);
fisadmaster 17-Nov-18 13:48pm    
I try that too, same problem
[no name] 17-Nov-18 13:51pm    
Ok, give me "un rato", I will try to Setup a small test Project.
[no name] 17-Nov-18 14:21pm    
It was simply a small typo. I corrected my answer.
a.) void SetCallback // void instead of bool (was not the Problem)
b.) _CPPCallBack= (CPPCallBack)Marshal.GetDelegateForFunctionPointer(
cppCallBack,
typeof(CPPCallBack));
instead
_CPPCallBack= (CPPCallBack).Marshal.
Is there a reason the console has to be in C++? Is this a dumbed-down example so you can get this working in another, more complicated context, like a legacy C++ app or COM object?

If not, then ...

1) Why not use C++/CLI which is also managed code?

or

2) You can write a console app in C#. So that may resolve the issue for you.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900