|
Hi,
I am in need of a MTA (Multithreaded) COM component for one of my application.
I would like to know if VC# can be used to develop the MTA COM component instead of VC++? If possible, how? or any info regarding it will be helpful.
Thanks in advance.
|
|
|
|
|
Hi,
When you program COM components in C++ you genereally use ATL, wich helps you a lot to deal with the COM gore details.
Since C# is a managed Language that runs over the .NET framework it was not designed to support COM developing which is an older unmanaged technology
If you want to use COM components from you C# App I strongly recommend you to program them in C++ and loading them into your C# project.
But you should first evaluate if its strongly necessary to use COM instead of a .NET component programmed in C#
JO
|
|
|
|
|
I want to make a function in COM dll which receive one character string and returns one character string. Since scripting languages dont use char* please suggest how to make this function in COM and how to use it. Please give any sample.
Manoj Kumar Chauhan
|
|
|
|
|
[id(...)] HRESULT SomeMethod([in] BSTR inString, [out,retval] BSTR * outString); In script this method can be used as
string2 = obj.SomeMethod(string1)
string2 = obj.SomeMethod("text1")
With best wishes,
Vita
|
|
|
|
|
Thanks it's working
Now if i use CHAR* instear of BSTR* then will it work for scripting language?
Please give some samples where to use BSTR* and CHAR* for scripting & non scripting language. If function inside COM dll takes CHAR* then i should pass BSTR if i'm using dll in scripting language
please give some samples for this
Manoj Kumar Chauhan
|
|
|
|
|
Now if i use CHAR* instead of BSTR* then will it work for scripting language?
No. At the most, [in] parameter might be considered as WCHAR*.
Please give some samples where to use BSTR* and CHAR* for scripting & non scripting language. If function inside COM dll takes CHAR* then i should pass BSTR if i'm using dll in scripting language
COM object doesn't use "CHAR*" in specification of functions, but can convert "CHAR*" to "BSTR" and viceversa.
With best wishes,
Vita
|
|
|
|
|
Thanks for explanation
So you mean it's always preferable to use BSTR for COM not any char*
And if i make any function in COM which takes char* as input then i need to pass char* when i call this function. Is it right?
Because ATL gives the option to make char* for any function argument so i can give it. My question is how i'll handle this char* in scripting language
Manoj Kumar Chauhan
|
|
|
|
|
When I spoke "COM object doesn't use "CHAR*" in specification of functions", I meant that for string parameter, not for CHAR parameter, which is valid in COM. So you can write
f(..., [in] CHAR* c, ...)
f(..., [in,out] CHAR* c, ...)
f(..., [out] CHAR* c, ...)
f(..., [out,retval] CHAR* c) but you will be able to pass only one symbol (or one byte), not the whole string.
With best wishes,
Vita
|
|
|
|
|
Thanks for your explanation
Is it possible if we pass any iostream object to COM function and COM function write some text in the file attached to iostream object and return.
Manoj Kumar Chauhan
|
|
|
|
|
"iostream" object is C++ object, not accessible directly from scripts and non-C++ clients and unallowed in COM accordingly.
With best wishes,
Vita
|
|
|
|
|
Thanks. There is one more doubt please clear this also.
If i want to return any variable length string from COM then i can allocate memory in COM and return it to exe (return BSTR*). Finall exe which's using the COM will free the memory. Is this OK? How to make same parameter as input/output in COM function?
How to return more than one string through COM function. suppose if i have function
int func(BSTR inputstring, BSTR* outstring1, BSTR* outstring 2);
Here i want to return 2 strings from this function.
COM dont give the option to pass output argument when we call the function
Manoj Kumar Chauhan
|
|
|
|
|
I implement one function in COM which allocate some memory to array and return this.
int AllocateData(int length, BSTR* OutArray)
{
// there is some data in a ansi array, i return this data from this COM function
wchar_t* wstr = (wchar_t*)calloc(sizeof(WCHAR),length+1);
MultiByteToWideChar(CP_ACP, 0, ansiarray, length, wstr, length) ; free(ansiarray);
*OutArray = (BSTR)wstr;
}
When i use this dll i call this function like
BSTR st;
st = cominterface->AllocateData(500);
When this function is called i get some error for memory leak. Please suggest how to fix it.
Manoj Kumar Chauhan
|
|
|
|
|
MKUser wrote: COM dont give the option to pass output argument when we call the function
That's not true (see the [OUT] IDL attribute).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Thanks. As per your comments i have solved the error when use [out] in idl file. But if i use [out,retval] then i get error.
I create a sample. Please check the below code.
main()
{
BSTR ab;
ab = allocmem();//i get run time memory error when return from this function
}
_bstr_t allocmem()
{
BSTR x;
allocmem2(&x);
return _bstr_t(x, false);
}
void allocmem2(BSTR *x)
{
char ansi[27];
memset(ansi,0,27);
for(int i = 0; i < 26; i++)
ansi[i] = 48 + i + 1;
wchar_t* wstr = (wchar_t*)calloc(sizeof(WCHAR),26);
MultiByteToWideChar(CP_ACP, 0, ansi, 26, wstr, 26) ;
*x = (BSTR)wstr;
}
Please suggest how to solve this error.
Manoj Kumar Chauhan
|
|
|
|
|
BSTR are strange beasts, you need to use SysAllocString [^](or similar) to allocate a new BSTR object.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Ok Let me explain my problem in detail.
In COM i create one function which takes one input and another output argument
idl file contains
HRESULT functionname([in] int length,[out,retval] BSTR* OutArray)
In function definition in COM class
HRESULT functionname(int length,BSTR* OutArray)
{
WSTR warray;
suppose warray contains some string and i want to return that string so i'll write
*OutArray = (BSTR) warray;
or if i try with following code then i think it's not correct
*OutArray = SysAllocString(wstr);
}
i use this dll and call it like
BSTR str;
str = cominterface->functionname(pass input length here);
When i build exe it generate tlh and tli files.
The tli file contains following code for that function
inline _bstr_t IExportComDll::functionname( int length ) {
BSTR _result = 0;
HRESULT _hr = raw_functionname(length, &result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _bstr_t(_result, false);
}
Now please tell me where i can change the code. Where to use SysAllocString. I cant change the code inside tli file. This function returns a string. So ATL write its wrapper code in tli file. When i call this function in some exe,After returning from wrapper code of tli file i get memory error because it try to free BSTR string.
Manoj Kumar Chauhan
|
|
|
|
|
Why do you need to pass the length?
For instance the following should work fine:
HRESULT functionname(BSTR * OutArray)
{
*OutArray = SysAllocString( L"Foo");
}
in the client application you may do
BSTR str;
str = cominterface->functionname();
You should also remember to call SysFreeString(str); there.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I'm doing following
HRESULT functionname(BSTR * OutArray)
{
// suppose there is some ansi array which contains some data
// length is int type which keeps size of this ansi array
wchar_t* wstr = (wchar_t*)calloc(sizeof(WCHAR),length+1);
MultiByteToWideChar(CP_ACP, 0, ansiarray, length, wstr, length) ;
free(ansiarray);
ansiarray= NULL;
*OutArray = SysAllocString( wstr);//(BSTR)wstr;
memset(wstr,65,sizeof(WCHAR) * length+1);
free(wstr);
wstr = NULL;
}
When i use this dll
BSTR st;
st = functionname();
After this statement st contains some garbage data.
While when i debug the code in tli file, it returns valid data
inline _bstr_t IExportComDll::functionname( )
{
BSTR _result = 0;
HRESULT _hr = raw_functionname(&_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _bstr_t(_result, false);
//here _result contains valid data which is returned by COM function
//HRESULT functionname(BSTR * OutArray)
}
Now please tell me where i'm wrong. Please correct my mistake
Manoj Kumar Chauhan
|
|
|
|
|
MKUser wrote: inline _bstr_t IExportComDll::functionname( )
The above function returns a _bstr_t instance. Possibly it cannot assigned as it stands to as BSTR variable, hence you need either to
define st as _bstr_t , for instance
_bstr_t st;
st = YourCOMInterface->functionname();
or
use the Detach method of _bstr_t (see [^]), for instance
BSTR st;
st = (YourCOMInterface->functionname()).Detach();
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Thanks
it's working now
Manoj Kumar Chauhan
|
|
|
|
|
Imported "cominterface->functionname" returns C++ class "_bstr_t", which has a destructor and misleading "operator wchar_t*".
Valid variant is:
str = cominterface->functionname(pass input length here).copy();
With best wishes,
Vita
|
|
|
|
|
Thanks it's also working
Manoj Kumar Chauhan
|
|
|
|
|
If i want to return any variable length string from COM then i can allocate memory in COM and return it to exe (return BSTR*). Finall exe which's using the COM will free the memory. Is this OK?
Yes.
String Manipulation Functions Descriptions
------------------------------------------
SysAllocString Creates and initializes a string.
SysAllocStringByteLen Creates a zero-terminated string of a specified length (32-bit only).
SysAllocStringLen Creates a string of a specified length.
SysFreeString Frees a previously created string.
SysReAllocString Changes the size and value of a string.
SysReAllocStringLen Changes the size of an existing string.
SysStringByteLen Returns the length of a string in bytes (32-bit only).
SysStringLen Returns the length of a string.
There are some C++ classes working with BSTR: CComBSTR, _bstr_t.
How to make same parameter as input/output in COM function?
You can specify [in] for input parameter and [out] for output. I have shown this recently.
How to return more than one string through COM function. suppose if i have function
int func(BSTR inputstring, BSTR* outstring1, BSTR* outstring 2);
Here i want to return 2 strings from this function.
Simple answer is:
int func([in] BSTR inputstring, [out] BSTR* outstring1, [out] BSTR* outstring 2)
But this code will not be working with some scripts, because the basic data for script is VARIANT and not all IDispatch handler can process these data. Moreover, for example, Jscript cannot receive any [out] data at all, but only with [out, retval].
With best wishes,
Vita
|
|
|
|
|
Vi2 wrote: "iostream" object is C++ object, not accessible directly from scripts
True.
Vi2 wrote: and unallowed in COM accordingly
False. It's not allowed in COM automation only.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Automation clients, such as scripts, deals only with BSTR , hence you need to use BSTR s if your COM server needs to support them.
On the other hand, clients such as C++ applications (or even VB6 ones) may use server methods accepting char * .
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|