C++/Dll help
Expert: Ralph McArdell - 3/18/2005
Questionok i am trying to make a dll, that in c++.net that i can access from vb.net. I made a Class library(.net) project. I ccan get it to compile and i can add it to my vb project but i can figure out how to access the functions with in.
this is the code i have
//////////////sink.h
// sink.h
#pragma once
#include <dshow.h>
#include <Sbe.h>
using namespace System;
namespace sink
{
public __gc class Class1
{
// TODO: Add your methods for this class here.
void sink::Class1::sinkfile(LPSTR szFileName,IBaseFilter *FileWriteFilter);
};
}
/////////////sink.cpp
// This is the main DLL file.
#include <afxdisp.h>
#include "stdafx.h"
#include "sink.h"
#include <atlconv.h>
//sinkfileLIBRARY sink
void sink::Class1::sinkfile(LPSTR szFileName,IBaseFilter *FileWriteFilter)
{
USES_CONVERSION;
HRESULT hr;
IFileSinkFilter *m_pFileWriterControl;
hr=FileWriteFilter->QueryInterface(IID_IFileSinkFilter, (void**)&m_pFileWriterControl);
if (SUCCEEDED(hr))
hr = m_pFileWriterControl->SetFileName(T2W(szFileName), 0);
}
////////////sink.def
LIBRARY sink
AnswerFirst I shall apologise for any shortcomings in this answer. Your question is not really a C++ question as it related to using a specific implementation of C++ with an environment for which non-standard extensions and rules apply - namely .NET and the CLR together with VB .NET which obviously has little to do with C++. Secondly it is also a variation on C++ that I have not un until today had to get to grips with. I am in no way a .NET or VB expert...
However I would suggest that if you are using C++ in managed mode to work with other .NET citizens such as VB .NET then you should only use CLR compatible types when passing data in and out of functions. For example do not pass LPCSTR and the like, pass .NET framework System::String types around instead (in fact it seems that GC pointers to System::String and the like are what should be passed). It seems that a pointer to a CLR controlled type such as System::String will be __gc pointers by default and pointers to non-CLR types will _not_ be GC pointers by default i.e. they will be __nogc pointers to the application's C++ heap or wherever.
Of course you should really read up on the rules and options pertaining to using C++ and types with the .NET CLR environment. Try the MSDN library under such sections as .NET Development / Visual Studio .NET / Visual C++ / Managed Extensions for C++ Programming - all of this may be of interest but there are various parts that may be of particular use - the sections under the Migration Guide area for example. If you do not have a local copy of the MSDN library then you can find it online at
http://www.msdn.microsoft.com/ - however as a version of this is in fact the documentation for Visual Studio .NET then I see no reason why you do not have a local copy available.
Now on the VB .NET side you need to add a reference to your managed C++ class library assembly to the VB .NET project - you will notice the references pseudo folder for the project in the solution explorer - right clicking on this and selecting add references brings up a tabbed dialog. Assuming your Managed C++ class library project is part of the same solution then you should be able to locate it listed on the Projects tab.
I tried your scenario out using a simple hello world type of application. In fact it uses a managed C++ class library project called ManagedCPPLib which contains a class called Greeting:
// ManagedCPPLib.h
#pragma once
using namespace System;
namespace ManagedCPPLib
{
public __gc class Greeting
{
public:
Greeting( String __gc * greet )
: mGreet( greet )
{
}
String __gc * Hi( String __gc * name );
private:
String __gc * mGreet;
};
}
Note that I have played safe and explicitly made all pointers __gc pointers and that I pass around CLR System::String pointers. This is my first attempt at managed C++ after all!
The idea is that a greeting instance's Hi member function will return a greeting string which uses the name it is passed combined with the greeting string it was constructed with - so if we have a Greeting object like so:
Greeting greet(S"Hi ");
greet( S"John");
Would return "Hi John" (S appears to be another MS extension to C++ used to create literal CLR System::String objects).
The implementation of Greeting::Hi looks like so:
// This is the main DLL file.
#include "stdafx.h"
#include "ManagedCPPLib.h"
namespace ManagedCPPLib
{
String __gc * Greeting::Hi( String __gc * name )
{
String * greetingParts __gc [] = { mGreet, name };
return String::Concat(greetingParts);
}
}
Next I created a VB .NET Windows project in the same solution and added a Users Name edit box for a name to be entered a Greet button to trigger a call to ManagedCPPLib:: Greeting::Hi and a Greeting label to display the results to the automatically created form. I added a reference to ManagedCPPLib to this project then added a click handler for the Greet button:
Private Sub Greet_Click(ByVal sender As System.Object
, ByVal e As System.EventArgs
) Handles Greet.Click
If UsersName.Text.Length > 0 Then
Dim greet As New ManagedCPPLib.Greeting("Hi ")
Greeting.Text = greet.Hi(UsersName.Text)
End If
End Sub
As this is my first venture into this area my example is probably not the only or even the best way to do things but it does demonstrate how to use CLR objects defined using managed C++ from a VB .NET project.
I hope this helps you. Good luck.