Reputation: 150
I am trying to write a CLI wrapper around some low-level COM-related calls. One of the operations that I need to do specifically is to get a specific value from a PROPVARIANT
, i.e.:
pwszPropName = varPropNames.calpwstr.pElems[dwPropIndex];
where pwszPropName
is documented to be an LPWSTR
type and dwPropIndex
is a DWORD
value passed into the function by the user.
I have a native function defined as follows:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, wchar_t *PropertyName)
I would like to return the value of pwszPropName
via *PropertyName
.
Is the wchar_t*
type the best way to do this, and would I need to pin *PropertyName
in my CLI to ensure it does not move in memory? Do I need to define the length of *PropertyName
before passing it to native code (buffer)?
If wchar_t*
is the right variable type to pass into the native function, what is the proper conversion of LPWSTR
to whar_t*
, and how then would you convert that value to System::String
?
I have tried a number of different techniques over the past few days and can't seem to get anything right.
------------UPDATE------------
Here is my full code. First, the CLI:
String^ MetadataEditor::GetPropertyNameByID(unsigned int ID)
{
LPWSTR mPropertyName = L"String from CLI";
m_pCEditor->GetPropertyNameByID(ID, mPropertyName);
//Convert return back to System::String
String^ CLIString = gcnew String(mPropertyName);
return CLIString;
}
And the native code:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, LPWSTR PropertyName)
{
HRESULT hr = S_OK;
LPWSTR myPropName;
PROPVARIANT varNames;
PropVariantInit(&varNames);
hr = m_pMetadata->GetAllPropertyNames(&varNames);
if(hr != S_OK)
{
PropVariantClear(&varNames);
return hr;
}
myPropName = varNames.calpwstr.pElems[ID];
PropertyName = myPropName;
PropVariantClear(&varNames);
return hr;
}
It doesn't seem like the value (myPropName
) is set properly and/or sustained back into the CLI function because the CLI returns the value I set on mPropertyName
before calling the native function.. I'm not sure why or how to fix this.
UPDATE!!!!
I suspected my problem had something to do with variables going out of scope. So I changed the C++ function definition as follows:
LPWSTR GetPropertyNameByID(DWORD ID, HRESULT ErrorCode);
After adjusting the CLI as well, I now get a value returned, but the first character is incorrect, and in fact can be different with every call. I tried using ZeroMemory()
in the native class before assigning the output of the PROPVARIANT
to the variable (ZeroMemory(&myPropName, sizeof(myPropName +1));
but still no luck.
Upvotes: 0
Views: 213
Reputation: 43331
You can design unmanaged function by the following way:
HRESULT CMetadataEditor::GetPropertyNameByID(DWORD ID, LPWSTR PropertyName, size_t size)
{
....
wcscpy(PropertyName, varNames.calpwstr.pElems[ID]); // or wcsncpy
...
}
PropertyName
is the buffer allocated by caller, size
is its size. Inside the function wcscpy
or wcsncpy
the string varNames.calpwstr.pElems[ID]
to PropertyName
. Client code:
WCHAR mPropertyName[100];
m_pCEditor->GetPropertyNameByID(ID, mPropertyName, sizeof(mPropertyName)/sizeof(mPropertyName[0]));
Think, for example, how GetComputerName
API is implemented, and do the same
Upvotes: 0