|
-
July 23rd, 2009, 11:56 AM
#1
Calling Visual Basic 2008 functions from VC++2008
Hi,
I am new to mixed language programming and need to call a VB 2008 function (for which I have the source code) from a C++ code. I have Visual Studio 2008 with VB and VC++.
I searched through the web for several days now and getting extremely confused and frustrated because all methods seem to either imply that using VB6 would be simpler (eg, http://support.microsoft.com/kb/194873 which I am unable to follow in VS2008 because there are no activeX dlls..), or give incomplete solutions that I am unable to get compiled (eg, http://msdn.microsoft.com/en-us/libr...zx(VS.71).aspx).
Please, could somebody post a working example on how to call a simple VB code (below) from a simple C main unit (also below) using Visual Studio 2008?
I just want the simplest example that works and will build up from there - at the moment just getting nowhere after several days of trying solutions from the web :-( I have previously worked with COM objects etc, but just cant get my head around the C++/VB coupling and dont know the syntax for it..
Many thanks in advance!
--------------
' VB code to be called
Option Explicit On
Public Class Class1
Public Function vbfunk(ByVal x As Integer) As Integer
MsgBox(x)
vbfunk= x
End Function
End Class
----------------------------
// C code to call VB
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#import "vbdll.tlb" no_namespace
int main()
{
int rst;
// I understand I need a COM-type DLL??
//CoInitialize(NULL);
// some connection to add here
rst=vbfunk(1);
//CoUninitialize();
return 1;
}
-
July 24th, 2009, 01:11 AM
#2
Re: Calling Visual Basic 2008 functions from VC++2008
http://support.microsoft.com/default.aspx/kb/817248
This article describes how to create VB .NET project and register it for COM interoperability. Having COM server, you can call it from C++ using standard COM client code (#import, CreateInstance etc.).
-
July 24th, 2009, 02:31 AM
#3
Re: Calling Visual Basic 2008 functions from VC++2008
thank you very much Alex - I am starting to get there. Can you recommend a similar "how to" knowledge article for writing the COM interface - as I mentioned I am quite new to this and though I had used other peoples COM code I would like to have a cleaner understanding.
-
July 24th, 2009, 06:09 AM
#4
Re: Calling Visual Basic 2008 functions from VC++2008
Writing the COM interface? In what language?
-
July 24th, 2009, 08:39 AM
#5
Re: Calling Visual Basic 2008 functions from VC++2008
there are lots of COM article on codeguru and codeproject in c++ and other language
regards
-
July 24th, 2009, 01:08 PM
#6
Re: [RESOLVED] Calling Visual Basic 2008 functions from VC++2008
I attach a working example - hopefully somebody may benefit from my 10 consecutive hrs of figuring this out ... jeez I am slow sometimes ...
Alex - thanks for pointing me in the right direction - I previously used COM interfaces from Fortran (yikes, a bit embarassing to admit on this forum :-)) and so here I had to learn the C++ syntax (as well as the VB syntax for implementing the Interface) - too many new things just to use some dialog boxes and automation scripts!
The posts by Siddhartha
http://www.codeguru.com/forum/archiv.../t-364152.html
http://www.codeguru.com/forum/showthread.php?t=354953
were helpful but didnt seem to work here (they result in runtime Debug Assertion failure p!=0).
The http://msdn.microsoft.com/en-us/libr...zx(VS.71).aspx has an almost-working code that had to be modified (evolution?). I created a shorted version to highlight the concepts.
The 2004 blog http://charlesvaz.blogspot.com/2004/...ct-from-c.html suggested an instantiation procedure with better error checking properties (?).
The limitations of the code below are:
1) the VB namespace appears not actually used (though all procedures work). I am unsure why that is: The MSDN examples have them, and consequently do not compile ...
2) The "smart pointer" approach doesnt work... any ideas anyone?
3) As I posted on http://www.codeguru.com/forum/showthread.php?t=481490, there seems to be a problem when the code is modified to pass string arguments (if C++ sends a string exceeding 30 chars, VB receives a blank 0-length string, bizarre..)
Any idea what could be causing these problems? thanks in advance as usual!
===============================
// CPP08_CONCLR_CALLZ_VB08_DLLCLASSLIB_1.cpp : main project file.
// This file connects to a VB Class Library DLL using the COM approach
// Can be built as a C++ Win32 or CLR console project in VS2008 (not sure whats the diff??).
// With appropriate changes, the approach below can probably be built as DLL, etc.
#include "stdafx.h"
#include "iostream"
//#include "atlbase.h" // needed only for CComQIPtr (methods 1 & 2, dont work here anyway)
using namespace std;
#import "path\VB08_DLLCLASSLIB_1.tlb" raw_interfaces_only no_namespace
//using ComClass1Lib // does not work: VB-DLL namespace seems unaccessible ...
int main()
{
cout << left << "Inside C++ main" << endl;
HRESULT hr = CoInitialize(NULL);
int ok=-10;
//-----------------------
// Siddhartha's methods from http://www.codeguru.com/forum/archiv.../t-364152.html
// Do not seem to work here ...
// Use Smart pointer (only for methods 1 and 2)
// CComQIPtr <IComClass1> pIComClass1;
// Method 1: Using Prog Id [Debug assertion failure p!=0 in VB myFunction]
// if (SUCCEEDED (pIComClass1.CoCreateInstance (L"VB08_DLLCLASSLIB_1.ComClass1")))
// {ok=1;}
// else
// {ok=50;}
// Method 2: Using Class Name [Debug assertion failure p!=0 in VB myFunction]
// if (SUCCEEDED (pIComClass1.CoCreateInstance (__uuidof (ComClass1)))){ok=1;}
// else {ok=50;}
//-----------------------
// Method 3 (adapted from MSDN knowledgebase
// http://msdn.microsoft.com/en-us/libr...zx(VS.71).aspx
// IComClass1Ptr pIComClass1(__uuidof(ComClass1));
// _ComClass1Ptr pIComClass1(__uuidof(ComClass1)); // interchangeable
// Method 4 (from a 2004 blog) - Gives best error checking capabilities
IComClass1Ptr pIComClass1 = NULL; hr = S_OK;
if (SUCCEEDED (pIComClass1.CreateInstance( __uuidof(ComClass1 ) ))){ok=1;}
if(ok==-10) {cout << left << "UNKNOWN status in COM" << endl;}
else if(ok==1){cout << left << "SUCCEEDED IN CreateInstance"<<endl;}
else {cout << left << "ERROR IN CreateInstance"<<endl;}
// Initialize variables to send to VB
long x=10;
VARIANT_BOOL reslt=false;
cout << left << "BEFORE" << endl;
cout << left << "x=" << x << endl;
cout << left << "reslt=" << reslt << endl;
// Call the VB routine from the DLL
hr=pIComClass1->myFunction(&x,&reslt);
// ideally, check hr==0 here, if hr!=0 then error occured
// Check variables returned by VB
cout << left << endl << "BEFORE" << endl;
cout << left << "x=" << x << endl;
cout << left << "reslt=" << reslt << endl;
CoUninitialize();
return 0;
}
===============================
' VB script to be built as Class Library DLL in VS2008.
' 1. File > New > Project > Visual Basic > Class Library > "VB08_DLLCLASSLIB_1"
' 2. Delete file Class1.vb
' 3. Project > Add Class > COM Class
' 4. Save the COM GUIDs that are automatically generated in the COM class file in step 3
' 5. Paste the script below into the COM class file (overwrite everything)
' 6. Paste your (saved) COM GUIDs into the COM class file
' 7. Ensure 'Register for COM interop' is clicked in project settings > compile
' Comments:
' 1. The full Namespace with Implementation is good programming practice, but the
' not using them is probably ok as well - as long as the Interface is implemented!
Option Explicit On
Namespace ComClass1Lib
Public Interface IComClass1
Function myFunction(ByRef x As Integer) As Boolean
End Interface
<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _
Public Class ComClass1
Implements IComClass1
#Region "COM GUIDs"
' These GUIDs provide the COM identity for this class
' and its COM interfaces. If you change them, existing
' clients will no longer be able to access the class.
Public Const ClassId As String = "c91a80a9-07d4-41d6-95d6-af91925f5f00"
Public Const InterfaceId As String = "680d8540-ec24-4b63-939c-93af02050728"
Public Const EventsId As String = "f04ad9b1-c78e-4be5-b524-3c06ef3f2554"
#End Region
' A creatable COM class must have a Public Sub New()
' with no parameters, otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()
End Sub
Public Function myFunction(ByRef x As Integer) As Boolean _
Implements IComClass1.myFunction
MsgBox(x)
x = x + 1
Return False
End Function
End Class
End Namespace
===============
Last edited by kangazzz; July 24th, 2009 at 04:10 PM.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|