I am making a program partly written in C++ and C#. C# is mainly used for GUI. Inside my C++ code I create PowerPoint COM object and open a presentation in it.
At some point I need to reference PowerPoint::_PresentationPtr
in my C# code. To call methods and so on.
PowerPoint::_PresentationPtr
is a smart pointer made with
_COM_SMARTPTR_TYPEDEF(_Presentation, __uuidof(_Presentation));
It is defined by Visual studio in msppt.tlh Microsoft.Office.Interop.PowerPoint.dll binding:
struct __declspec(uuid("91493463-5a91-11cf-8700-00aa0060263b"))
/* interface */ PresEvents;
struct /* coclass */ Presentation;
struct __declspec(uuid("9149349d-5a91-11cf-8700-00aa0060263b"))
/* dual interface */ _Presentation;
/* PowerPoint::_PresentationPtr */
_COM_SMARTPTR_TYPEDEF(_Presentation, __uuidof(_Presentation));
So it makes PowerPoint::_PresentationPtr
for ease of use the COM object in C++, calling methods etc.
And this is C# Microsoft.Office.Interop.PowerPoint.Presentation
namespace Microsoft.Office.Interop.PowerPoint
{
[CoClass(typeof(PresentationClass))]
[Guid("9149349D-5A91-11CF-8700-00AA0060263B")]
public interface Presentation : _Presentation, PresEvents_Event
{
}
}
I have an Interface in C# with C++ implementation so I can access it in C# part of the application.
ApplicationHost.cs
namespace SampleWpfUserControlLibrary
{
public interface IApplicationHostWindow
{
void OpenDocument();
PowerPoint.Presentation GetPresentation();
void Exit();
}
}
ApplicastionHost.h
#pragma once
#using <SampleWpfUserControlLibrary.dll>
using namespace SampleWpfUserControlLibrary;
ref class ApplicationHostWrapper : IApplicationHostWindow
{
public:
ApplicationHostWrapper(CMainFrame * pMainFrame)
{
_pMainFrame = pMainFrame;
}
virtual void __clrcall Exit() sealed
{
_pMainFrame->SendMessage(WM_CLOSE);
}
virtual void __clrcall OpenDocument() sealed
{
_pMainFrame->OpenDocument();
}
virtual PowerPoint::_PresentationPtr __clrcall GetPresentation() sealed
{
CMFCBindDoc * pDoc = _pMainFrame->GetDocView()->GetDocument();
return pDoc->GetPresentation();
}
};
However it does not compile. Arguing that GetPresentation()
is not implemented.
As the types do not match.
Update:
What should I return in C++ code PowerPoint::_Presentation
or PowerPoint::_PresentationPtr
and what should I map it to in C# part? Or How do convert it to Microsoft.Office.Interop.PowerPoint in the C#? I just want to reference it in C#.
These are the errors I get:**
- Error 3 error C2259: 'ApplicationHostWrapper' : cannot instantiate abstract class
Source\Application\MainFrm.cpp 146 1 Application- Error 1 error C3766: 'ApplicationHostWrapper' must provide an implementation for the interface method
'Microsoft::Office::Interop::PowerPoint::Presentation
^SampleWpfUserControlLibrary::IApplicationHostWindow::getPresentation(void)' source\application\ApplicationHostWrapper.h 39 1 Application
In Object Browser getPresentation() method is this:
unknown-type^ getPresentation() Member of SampleWpfUserControlLibrary::IApplicationHostWindow
Okay, I found solution.
in ref class ApplicationHostWrapper : IApplicationHostWindow
by calling GetInterfacePtr() on a smart pointer we can get a pointer to interface.
virtual void* __clrcall GetPresentationPtr() sealed
{
CMFCBindDoc * pDoc = _pMainFrame->GetDocView()->GetDocument();
return (void*)pDoc->GetPresentation().GetInterfacePtr();
}
In C# Interface declaration ApplicationHost.cs:
namespace SampleWpfUserControlLibrary
{
public interface IApplicationHostWindow
{
void OpenDocument();
unsafe void* GetPresentationPtr();
void Exit();
}
}
And this allows us to make a method in managed code for example in a class:
private IApplicationHostWindow _hostWindow;
unsafe private PowerPoint.Presentation getPresentation(){
IntPtr preIntPtr = new IntPtr(_hostWindow.GetPresentationPtr());
return (PowerPoint.Presentation)Marshal.GetUniqueObjectForIUnknown(preIntPtr);
}
The only drawback is that it requires using /unsafe for compilation. And what could be the consequences I have no idea yet. If someone knows how to overcome /unsafe and do it differently you are welcome.