2

Is WCHAR in COM interfaces a good thing ?

I've been searching the internet for an answer to this question with no results.

Basically should char* / wchar* be used in COM or should i use BSTR instead ?

Is it safe or does it depend ?

In this code example its strings (code grabbed from a random source):

STDMETHOD(SetAudioLanguageOrder(WCHAR *nValue)) = 0; 
STDMETHOD_(WCHAR *, GetAudioLanguageOrder()) = 0;

I'm confused over when to use what with all marshaling, memory boundaries, etc. that comes up when talking about COM.

What about data buffers (byte*) ?

Carl Serl
  • 51
  • 6

3 Answers3

2

It depends on the context in which the caller will call you. First, if you use a non-automation type, marshaling will not be automatically performed for you. Therefore, you'll end up having to write your own marshaler to move a wchar_t* across process boundaries.

That said, there's no rule that says you can't pass a wchar_t* in a COM interface. There are many COM interfaces that pass custom types (structs, pointers to structs, callbacks, etc), and it's all just about your needs.

In your interface, if you do use WCHAR strings, I'd declare SetAudioLanguageOrder this way:

STDMETHOD(SetAudioLanguageOrder(const WCHAR *nValue)) = 0;

This makes it clearer who is (not) supposed to free the string, and provides more context as how to treat the string (the caller is discouraged from modifying the string, though the caller can certainly force that behavior if they want to write bad code).

The GetAudioLanguageOrder call is OK, but now the question is: who frees the returned string, and how should it be freed? Via free(...)? Or C++ delete[]? If you use a BSTR, then you know - use SysFreeString. That's part of the reason to use BSTR's instead of WCHAR strings.

Kevin Hsu
  • 1,726
  • 11
  • 14
1

If you are going to support dual interfaces and clients other than C++, use BSTR. If all callers are C++, then WCHAR* is fine.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
0

You will have to be able to know the length of that array in one way or another. In C or C++ it's typical to use null-terminated strings and you often use them within one process - the callee accesses the very same data as the caller prepared and null-terminated.

Not the same with COM - you might want to create an out-proc server or use your in-proc server in a surrogate process and then you'll need marshalling - a middleware mechanism that transmits that data between processes or threads - to work. That mechanism will not know about the size of the string unless you one of MIDL attributes such as size_is to specify the right array size. Using those attributes will require an extra parameter for each array - that complicates the interface and requires extra care while dealing with data.

That said, in most cases you get a more fluent interface by just using BSTRs.

sharptooth
  • 167,383
  • 100
  • 513
  • 979