|
I know there have been numerous threads and articles regaring CString to BSTR conversion, but I can't seem to get the solutions given to work.
Here is what I have.
IN VB:
<br />
Private Declare Function GetNextCustomerID Lib "C:\Debug\DataAccess.dll" (CustomerID As String) As Long<br />
THEN:
<br />
Private Sub Form_Load()<br />
Dim TestStr As String<br />
Dim ret As Long<br />
<br />
ret = GetNextCustomerID(TestStr)<br />
If ret = 1 Then<br />
Label1.Caption = TestStr<br />
End If<br />
End Sub<br />
THEN, IN C++
<br />
extern "C" long __stdcall GetNextCustomerID(BSTR& CustomerID)<br />
{<br />
HRESULT hr = CoInitialize(0);<br />
long ret = 0;<br />
CString tmp;<br />
<br />
if(SUCCEEDED(hr))<br />
{<br />
dbReferenceNums dbR;
if(dbR.Open())<br />
{<br />
if(!dbR.IsEOF())<br />
{<br />
tmp.Format("%s%d", "CX", dbR.m_NextAvailCustID);<br />
CustomerID = tmp.AllocSysString();<br />
ret = 1;<br />
}<br />
dbR.Close();<br />
}<br />
CoUninitialize();<br />
}<br />
return ret;<br />
}<br />
if the string is "CX1504", then the result that is printed in VB is "C" and that is all. I assume it is because a null character is encountered, because there is a null character between each character of the string. But, I can't figure out how to prevent this. I thought BSTRs were WCHAR-based strings and this behavior (nulls between each char) would be expected, but it is not interpretted correctly by VB.
Thanks in advance for any help you can provide.
raj.
|
|
|
|
|
Your issue is not connected with COM.
It's a way to call the DLL's function. VB simulate the parameter for you depending on its ANSI or UNICODE version.
ByVal xxx As String => TCHAR* xxx
ByRef xxx As String => TCHAR* *xxx as SysAllocStringByteLen does
You should use the VARIANT parameter instead.
With best wishes,
Vita
|
|
|
|
|
When calling a Declare d Sub or Function, VB6 ALWAYS translates a String into a null-terminated 8-bit char array (i.e. a normal C-style string of char ) - even if running on a Unicode-capable platform. If the string is passed ByRef it will be converted back on return.
What you should probably do is something like:
extern "C" long __stdcall GetNextCustomerID(char* CustomerID, long lSize)
{
long ret = 0;
dbReferenceNums dbR;
if(dbR.Open())
{
if(!dbR.IsEOF())
{
tmp.Format("%s%d", "CX", dbR.m_NextAvailCustID);
strncpy(CustomerID, tmp, lSize);
CustomerID[lSize] = '\0';
ret = 1;
}
dbR.Close();
}
return ret;
}
' VB code
Private Declare Function GetNextCustomerID _
Lib "C:\Debug\DataAccess.dll" _
(ByRef CustomerID As String, ByVal lSize As Long) As Long
Private Sub Form_Load()
Dim TestStr As String
Dim ret As Long
' Reserve space for string
TestStr = String(100, " ")
ret = GetNextCustomerID(TestStr, Len(TestStr))
If ret = 1 Then
Label1.Caption = TestStr
End If
End Sub VB does this because it has no knowledge of the parameters to the DLL function. If your C++ code was exposed as a COM object, VB would be able to obtain type information from the type library, and marshal data appropriately.
VB.NET users: the Declare statement functions as above, unless you specify the Unicode or Auto modifiers. For more control over marshalling, use the DllImportAttribute attribute.
|
|
|
|
|
well, I honestly feel like a complete idiot, but I cannot get this to work. I tried the code you listed above, but I receive an unhandled error (Access Violation) when control leaves my C++ DLL and returns to VB.
I have searched the internet and all the code sites I can think of to find a way to make this work. I can't find a single thing that will get this to work. I have many other functions that receive objects I have defined in VB classes, then the C++ code accesses a database, fills the properties of the object and then returns it to my VB exe. That all works fine. But, I cannot get the "simple" process of passing in a string, filling it, and returning it to VB.
arrrggggh!
Thanks anyway for your help.
I am stumped.
best regards
roger
|
|
|
|
|
Hello!
I want to implement simple COM object which will communicate with Oracle database somewhere on internet. It looks rather simple. But I have a possibility to use either C++ or C# technology. As I do not know C# very well: someone can help and put some comments - which technology would be simpler to write/manage ?
Or maybe there exists some ready-to-use sample?
Thanks for help
|
|
|
|
|
If you are creating a COM object, go with C++ and use ADO to talk to Oracle.
|
|
|
|
|
Hi,
I need to add a new method to my COM object.
Should I create a new COM object which aggregates the first and contains the new method?
Or is it OK to add a new method to an existing COM object?
Jeremy.
Jeremy Pullicino
C++ Developer
Homepage
|
|
|
|
|
Hi ,
Well it depends that how is ur COM object being used ,if ur object has been aggregated by some other client using its typelibs, or some other COM object has derived ur interface to write its own functionality in the existing method , then in that case if u will add Methos in the same interface , other clients of your COM object will stop working coz of changed interface , changed typelibs thats is where comes Versioning .
But if these are not the cases and u r just working on one client .then adding one more method will not create any problem.
well i know that much only
Regards
Abhishek Srivastava
Software Engg (VC++)
India ,Noida
Mobile no 9891492921
|
|
|
|
|
Strictly, you want to add a method to an interface. You don't need to create a new object, but you almost certainly want to contain a new interface.
If you're using ATL, this is almost trivial (amend the IDL, specify the new interface as deriving from the old one, and add the method; amend the declaration and definition of your class by having it derive from the new interface not the old one, amend any IDispatchImpl declaration to support the new interface rather than the old, add the interface into the interface map).
If you haven't published the interface (ie the client and server are not yet released) you can just amend the interface.
Steve S
|
|
|
|
|
I am trying to find a level 9.0 or 9.0b DirectX SDK on CD for development using C++/MFC and Win32 API. I can only find a download available on msdn and really don't want to take a couple days to download the 200+ MB file! Does anyone out there know if it's available on CD and if so, what's the URL to the site/page?
Thanks for any help in this regard.
Tom
|
|
|
|
|
The Windows Media 9 Series SDK provides a number of methods to read/write/edit.
Perhaps you want to have a look at Windows Media Format SDK from the following site:
http://www.microsoft.com/windows/windowsmedia/9series/sdk.aspx
It's not DirectShow but it's significantly smaller in size compared to the DirectX download.
|
|
|
|
|
Okay... thanks for the input!
Tom
|
|
|
|
|
how to show a message box in an ASP.NET page?
I am a Software Developer using C# on ASP.NET.
|
|
|
|
|
I would like to know if it is possible to wrapp other things than predefined types (like ints, floats and strings) with the VARIANT type.
I need to use a COM server function that takes a VARIANT as parameter. But tthat parameter has to be an object of type IXMLDocument. How can I cast the IXMLDocument object into a VARIANT one?
Thanks a lot
|
|
|
|
|
Hi,
I need to pass an ADODB.Stream to a COM object I have created in C++.
The object comes in as a VARIANT.
I guess I need to get the IDispatch and query interface for something.
Has anyone ever done this? All my tests have failed, most of which are reporting "no such interface supported"
thanks.
Jeremy Pullicino
C++ Developer
Homepage
|
|
|
|
|
I use automation to launch Excel, it's work but i don't know how do you do to close Excel process. I use CLSIDFromProgID and GetActive Object to start excel automation. I search a exemple to close automation.
Thanks
Jerome
|
|
|
|
|
In order to attach to Excel, you will have called CreateDispatch() and/or AttachDispatch(). There is a corresponding function ReleaseDispatch() which you can call when you do not need the interface open any longer.
Alternatively, you could use the second parameter of void AttachDispatch( LPDISPATCH lpDispatch, BOOL bAutoRelease = TRUE ) to autorelease the interface for you.
Note that Excel, or any other automaton, will not close until all the attached interfaces have been released.
|
|
|
|
|
Hi everyone,
I have an MFC app (with a CWinApp-derived object) that uses COM objects (Crystal Reports). The COM library is imported into my project via the #import directive. I'm using VStudio 6.0 sp5.
I've created a global object called _com_init:
struct ComInit {
ComInit() { ::CoInitialize(NULL); }
~ComInit() { ::CoUninitialize(); }
} _com_init_;
This way, I guarantee that COM will initialize before the _main() and terminate after the _main().
When my program reaches ~ComInit() and calls ::CoUninitialize(), I see the following message in my Debug Output Window:
First-chance exception in MyApp.exe (OLE32.DLL): 0xC0000005: Access Violation.
Any ideas? I've looked up other CoUninitialize threads in these forums, but couldn't figure out something that would solve my problem...
Thanks.
/=/=/=/=
Deus
/=/=/=/=
|
|
|
|
|
Watch carefully if you don't use the COM after the CoUninitialize . It looks weird but e.g. if you use the smart pointers or something it can easily happen that first is called a d-tor of the ComInit class and then destructor of smart ptr calling Release (=using COM)
|
|
|
|
|
Yeah, well, that's exactly the problem. The only place I use COM in this application is within the CWinApp class. I even tried working with the debugger, pressing F11 at the end of each funtion in order to get into all d-tors. Yes - I do work with com_ptr's (COM's version of auto pointers), but they're all destroyed before CoUninitialize, as far as I could tell.
Anything else I should check?
/=/=/=/=
Deus
/=/=/=/=
|
|
|
|
|
Hmm I would look also to variants and bstrs as well, because they uses COM too.
Some smartpointer in global variable...
Maybe some addref/release leak causing some OLE proxy/stub stuff remainig in memory until CoUnitialize is called (but I assume that's not the issue while you're using smartptrs)
|
|
|
|
|
There is use of bstrs in my code... what exactly should I check about them?
I don't have ANY global smart pointers. I only have local ones, and I checked with the debugger, that they all get released when they go out of scope...
/=/=/=/=
Deus
/=/=/=/=
|
|
|
|
|
I assume you're using _bstr_t or CComBSTR -> their behavior is exactly the same as smart pointers, therefore destructors should be called before CoUninitialize .
|
|
|
|
|
Call AfxOleInit() from your CWinApp::InitInstance() override. You are guaranteed not to have any of those problems after that.
Isaac Inyang
Ansyl Technologies
|
|
|
|
|
Try using the initinstance and the exitinstance to do the initialization and termination of the component...
this i guess should work perfectly...
You should be sure that when the destrcutor of the structure is called.
The World is getting smaller and so are the people.
|
|
|
|