C# COM dll called by a C++ app not returning strings

G

Guest

I have a C# dll with a COM interface that is successfully call by a C++
client. One of the parameters is a string, the method looks like

void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
string strOutput);

I make an assignment in the C# COM object to strOutput like
strOutput = some system.string
but the string is never returned to the C++ client, it always returns "". I
tried setting strOutput to a stack value like strOutput = "Ge"; and the
string is returned to my C++ client just fine. There seems to be some magic I
am missing???
 
W

Willy Denoyette [MVP]

sienaman said:
I have a C# dll with a COM interface that is successfully call by a C++
client. One of the parameters is a string, the method looks like

void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
string strOutput);

I make an assignment in the C# COM object to strOutput like
strOutput = some system.string
but the string is never returned to the C++ client, it always returns "".
I
tried setting strOutput to a stack value like strOutput = "Ge"; and the
string is returned to my C++ client just fine. There seems to be some
magic I
am missing???

What exactly do you mean with strOutput = some system.string

strOutput = "Ge"; Here "Ge" is a System.String and is by no way a stack
value.
Please post your failing code.

Willy.
 
G

Guest

Hi Willy,

Here is the code in question:

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{
void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
System.Text.StringBuilder strOutput);
}
public void Goofy(string strUserInput, out System.Text.StringBuilder
strOutput)
{
// the first letter in the input string is the one to operate on
char c = strUserInput[0];
if (c >= 'a' && c <= 'w')
{
// map the character to its key number
key = m_iKeyMap[c - 'a'];

if ((c - 'a' < m_iKeyMap.Length) && (c - 'a' >= 0))
{
key = m_iKeyMap[c - 'a'];

m_FTIterator.nextLevel(key);
if (m_FTIterator.hasNext())
{
// the value placed in strOutput does not make it back to the
// calling unmanaged client
strOutput = ((System.Text.StringBuilder) m_FTIterator.Current);

}
else
{
m_FTIterator.prevLevel();
}
}
}
}

Willy Denoyette said:
sienaman said:
I have a C# dll with a COM interface that is successfully call by a C++
client. One of the parameters is a string, the method looks like

void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
string strOutput);

I make an assignment in the C# COM object to strOutput like
strOutput = some system.string
but the string is never returned to the C++ client, it always returns "".
I
tried setting strOutput to a stack value like strOutput = "Ge"; and the
string is returned to my C++ client just fine. There seems to be some
magic I
am missing???

What exactly do you mean with strOutput = some system.string

strOutput = "Ge"; Here "Ge" is a System.String and is by no way a stack
value.
Please post your failing code.

Willy.
 
W

Willy Denoyette [MVP]

sienaman said:
Hi Willy,

Here is the code in question:

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{
void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
System.Text.StringBuilder strOutput);
}
public void Goofy(string strUserInput, out System.Text.StringBuilder
strOutput)
{
// the first letter in the input string is the one to operate on
char c = strUserInput[0];
if (c >= 'a' && c <= 'w')
{
// map the character to its key number
key = m_iKeyMap[c - 'a'];

if ((c - 'a' < m_iKeyMap.Length) && (c - 'a' >= 0))
{
key = m_iKeyMap[c - 'a'];

m_FTIterator.nextLevel(key);
if (m_FTIterator.hasNext())
{
// the value placed in strOutput does not make it back to the
// calling unmanaged client
strOutput = ((System.Text.StringBuilder) m_FTIterator.Current);

}
else
{
m_FTIterator.prevLevel();
}
}
}
}

Funny, you aren't returning a String but a StringBuilder, now the question
is what is m_FTIterator.Current supposed to return?
And why do you need a cast? If m_FTIterator.Current is a string you should
return strOutput = StringBuilder(m_FTIterator.Current); If it's not a string
you should make it a string.

Willy.
 
G

Guest

Good point about the StringBuilder. Here is a simplified version of the code
using strings, seems like making the strOutput an out parameter should do the
trick...

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{

void Goofy([Out, MarshalAs(UnmanagedType.LPWStr)] out> string strOutput);

}

public class Sleepy : ITSleepy
{

public void Goofy(out string strOutput)
{

strOutput = ((System.String) m_FTIterator.Current);
// at this point I have verified that strOutput contains the
// value returned by m_FTIterator.Current but the string does
// not make it back to the unmanaged C++ caller
}


Willy Denoyette said:
sienaman said:
Hi Willy,

Here is the code in question:

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{
void Goofy(string strUserInput,[Out, MarshalAs(UnmanagedType.LPWStr)] out
System.Text.StringBuilder strOutput);
}
public void Goofy(string strUserInput, out System.Text.StringBuilder
strOutput)
{
// the first letter in the input string is the one to operate on
char c = strUserInput[0];
if (c >= 'a' && c <= 'w')
{
// map the character to its key number
key = m_iKeyMap[c - 'a'];

if ((c - 'a' < m_iKeyMap.Length) && (c - 'a' >= 0))
{
key = m_iKeyMap[c - 'a'];

m_FTIterator.nextLevel(key);
if (m_FTIterator.hasNext())
{
// the value placed in strOutput does not make it back to the
// calling unmanaged client
strOutput = ((System.Text.StringBuilder) m_FTIterator.Current);

}
else
{
m_FTIterator.prevLevel();
}
}
}
}

Funny, you aren't returning a String but a StringBuilder, now the question
is what is m_FTIterator.Current supposed to return?
And why do you need a cast? If m_FTIterator.Current is a string you should
return strOutput = StringBuilder(m_FTIterator.Current); If it's not a string
you should make it a string.

Willy.
 
W

Willy Denoyette [MVP]

sienaman said:
Good point about the StringBuilder. Here is a simplified version of the
code
using strings, seems like making the strOutput an out parameter should do
the
trick...

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{

void Goofy([Out, MarshalAs(UnmanagedType.LPWStr)] out> string strOutput);

}

public class Sleepy : ITSleepy
{

public void Goofy(out string strOutput)
{

strOutput = ((System.String) m_FTIterator.Current);
// at this point I have verified that strOutput contains the
// value returned by m_FTIterator.Current but the string does
// not make it back to the unmanaged C++ caller
}
You could return a StringBuilder too using:
return strOutput = StringBuilder((String)m_FTIterator.Current);
But this is overkill in this case.

Willy.
 
G

Guest

My point is that the string created in the COM method should get stuffed into
the out parameter and returned to the client, but this is not happening??

Willy Denoyette said:
sienaman said:
Good point about the StringBuilder. Here is a simplified version of the
code
using strings, seems like making the strOutput an out parameter should do
the
trick...

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{

void Goofy([Out, MarshalAs(UnmanagedType.LPWStr)] out> string strOutput);

}

public class Sleepy : ITSleepy
{

public void Goofy(out string strOutput)
{

strOutput = ((System.String) m_FTIterator.Current);
// at this point I have verified that strOutput contains the
// value returned by m_FTIterator.Current but the string does
// not make it back to the unmanaged C++ caller
}
You could return a StringBuilder too using:
return strOutput = StringBuilder((String)m_FTIterator.Current);
But this is overkill in this case.

Willy.
 
W

Willy Denoyette [MVP]

If you return strOutput = "Somestring";
It works right?
However, if you return:
(String)m_FTIterator.Current
an empty string is returned.

That means that m_FTIterator.Current is null. Also, I asked what type
m_FTIterator.Current is and why you needed the cast, you didn't answer that
question.
Could you change your code into:

if ((m_FTIterator.Current) == null)
return "null";
else
return ((String)m_FTIterator.Current);

and test again?

Willy.



sienaman said:
My point is that the string created in the COM method should get stuffed
into
the out parameter and returned to the client, but this is not happening??

Willy Denoyette said:
sienaman said:
Good point about the StringBuilder. Here is a simplified version of the
code
using strings, seems like making the strOutput an out parameter should
do
the
trick...

using interop = System.Runtime.InteropServices;
[
interop.ComVisible(true),
interop.GuidAttribute("FF29F224-22CE-4168-8A50-0CE070E96117")
]
public interface ITSleepy
{

void Goofy([Out, MarshalAs(UnmanagedType.LPWStr)] out> string
strOutput);

}

public class Sleepy : ITSleepy
{

public void Goofy(out string strOutput)
{

strOutput = ((System.String) m_FTIterator.Current);
// at this point I have verified that strOutput contains the
// value returned by m_FTIterator.Current but the string does
// not make it back to the unmanaged C++ caller
}
You could return a StringBuilder too using:
return strOutput = StringBuilder((String)m_FTIterator.Current);
But this is overkill in this case.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top