all groups > dotnet interop > january 2007 >
You're in the

dotnet interop

group:

Typical C++ string to C# dll question


Typical C++ string to C# dll question Kyle Szklenski
1/25/2007 9:09:18 AM
dotnet interop:
Hi. I suppose I'm not the first to ask this, especially given that I
searched and found a few similar things posted here. None of them,
however, answered my question.

My question is this: I'm trying to pass a normal std::string from VC++
6.0 to a C# DLL. My .cpp file for my VC++ console application looks
like this:

#include "stdafx.h"
#import "ProblemTranslator.tlb" raw_interfaces_only

using namespace ProblemTranslator;
int main( int argc, char* argv[] )
{
// Initialize COM.
HRESULT hr = CoInitialize(NULL);

// Create the interface pointer.
ITranslatorPtr Trans( __uuidof( Translator ) );

// Call the Process method.
Trans->Process( ( BSTR )argv[ 1 ] );

// Uninitialize COM.
CoUninitialize();
return 0;
}

This was taken almost codatim (verbatim with respect to code) from the
MS website. It compiles fine. However, it's hitting an access violation
somewhere, and I'm not sure what the problem is. Here's the exact
access violation, which probably doesn't help:

First-chance exception in TranslatorConsole.exe (MSVCR80.DLL):
0xC0000005: Access Violation.

I've debugged it down to the point where it's definitely hitting the
violation when I call the Process function. It does not, however, get
that access violation when I call the DLL from another C# program. The
..tlb header file said the Process function takes a BSTR, so I tried
just casting to it. Is that the problem? If that's not it, the header
file declaration for the ITranslator interface looks like:

ITranslator : IDispatch
{
//
// Raw methods provided by interface
//

virtual HRESULT __stdcall Process (
BSTR File ) = 0;
};

Can anyone help?
Re: Typical C++ string to C# dll question Cholo Lennon
1/25/2007 4:04:12 PM
You cannot cast a c string to BSTR. Use CComBSTR (atlbase.h) or _bstr_t (comutil.h) classes instead:

Trans->Process(CComBSTR(argv[ 1 ] ));

or

Trans->Process(_bstr_t(CComBSTR(argv[ 1 ] ));

Another nasty (but efficient) way is to use USES_CONVERSION macro together with T2COLE macro (atlconv.h)

BTW if you #import without 'raw_interfaces_only' generated code (in .tlh and .tli) will use _bstr_t to manage BSTR strings. And
last... check for argc parameter to validate argv array.


Regards



--
Cholo Lennon
Bs.As.
ARG


[quoted text, click to view]

Re: Typical C++ string to C# dll question Mattias Sjögren
1/25/2007 7:50:45 PM
Kyle,

[quoted text, click to view]

I don't see any std::string used in your code.


[quoted text, click to view]

Yes. Try creating a proper BSTR, either with the SysAlloc* oleaut APIs
or a wrapper class like _bstr_t.


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Re: Typical C++ string to C# dll question Kyle Szklenski
2/1/2007 7:40:16 AM
Hi,

I thank you for your responses, both who replied. I'd like to respond
to both separately in one post so I take up less space.

Firstly, it's true there was no std::string in my C++ code. That's
because at the time of posting that, I had switched it over to the
BSTR attempt and forgot to go back and change it. :)

Responding to the second post will respond to the first here as well.
I tried both methods, and both throw a COM exception. In fact, the
exception is thrown in the same place for all three ways that I've
tried (casting to BSTR, and both of the methods mentioned below in the
quoted text). It is thrown here:


Interface* operator->() const throw(_com_error)
{
if (m_pInterface == NULL) {
_com_issue_error(E_POINTER);
}

return m_pInterface;
}

In COMIP.h. In the debugger, it steps over the m_pInterface == NULL,
which means it's not null, but when it hits the return statement, it
throws the error. Any clue what this exception could be? Thanks for
your responses again.

Kyle


[quoted text, click to view]

Re: Typical C++ string to C# dll question Kyle Szklenski
2/1/2007 7:59:50 AM
Hi, sorry about the second post to this. I just ran it through the
debugger gain, and put a break point directly inside the COMIP.h file,
and found out that it does actually think that the m_pInterface is
null. What's the solution there? Do I have to use regasm.exe for
the .tlb file inside the folder where I intend to have the tlb, dll,
and exe files? I didn't think I did.

Kyle

[quoted text, click to view]

Re: Typical C++ string to C# dll question Kyle Szklenski
2/1/2007 8:11:21 AM
One final message: I solved it. I did indeed have to register the COM
types in the folder that I'd intended to use them in. Is there a way
to make it so that I don't have to register it that way? Perhaps a
global registration? It's cool if that won't work. It just means we'll
have to put the SDK out on the server so we can register the COM types
there too, doesn't it? That's extra work that I'm not happy about
having to do, but I will if it'll make this thing work. :) Thanks all.

Kyle


[quoted text, click to view]

AddThis Social Bookmark Button