|
Hi,
I am writing this only after exhausting effort to search and find the solution was unsuccessful.
I am using Visual Studio 2005. The Test123 function written in C++ should be called from vb.net by using Interop Services.
The Testing.dll is a CLR dll.
Below is a simplified version of the C++ structure :
typedef struct TEST_STRUCT<br />
{<br />
long lTotal;<br />
int nRow;<br />
int nCol;<br />
CString sName;<br />
BOOL bFound;<br />
int item[100];<br />
} TEST;
Below is a simplified version of the structure declared in vb.net :
<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _<br />
Public Structure TEST_STRUCT<br />
' ''<System.Runtime.InteropServices.FieldOffsetAttribute(0)> _<br />
Public lTotal As Integer<br />
Public nRow As Integer<br />
Public nCol As Integer<br />
<System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)> _<br />
Public sName As String<br />
<System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> _<br />
Public bFound As Boolean<br />
<br />
'<System.Runtime.InteropServices.MarshalAsAttribute _<br />
'(System.Runtime.InteropServices.UnmanagedType.SafeArray, SafeArraySubType:=Runtime.InteropServices.VarEnum.VT_I4)> _<br />
<System.Runtime.InteropServices.MarshalAsAttribute _<br />
(System.Runtime.InteropServices.UnmanagedType.LPArray, SizeConst:=100)> _<br />
Public Item() As Integer<br />
End Structure<br />
<br />
Public Declare Auto Function Test123 Lib "Testing.dll" () As TEST_STRUCT<br />
What can work :
1) I can call the module Test123 from vb.net and it can run.
2) I can interop data for lTotal, nRow and nCol and receive at vb.net without any problem.
What my questions are :
1) How to interop data for sName, bFound and item[100]?
2) Which part I am wrong?
3) How should I declare the structure in vb.net to interop these data?
4) Can Interop support CString directly?
5) Is there any indirect way of marshaling which can work, such as doing the Interop in C# and then call from vb.net?
Your guidance on solving this problem is very much appreciated.
Thanks,
Goutam
|
|
|
|
|
Hi,
1.
AFAIK P/Invoke works equally well from VB.NET as from C#, so a C# detour does not make sense to me.
2.
To embed a fixed-size array inside a struct you need
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=100)>
3.
for the string, I'm not sure. You might define it as an IntPtr, and use one of the Marshal.PtrToStringXxx methods.
4.
as long as one struct member isn't marshaled correctly, everything that follows it may fail.
so start by putting the string last!
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Hello Mr. Luc Pattyn,
Thank you for your prompt reply and interest in this topic.
When I do the testing, I comment out all and test one by one as below. When I can interop every value I need, only then I will put them together :
<br />
typedef struct TEST_STRUCT<br />
{<br />
int item[100];<br />
} TEST;<br />
<br />
<br />
extern "C" __declspec(dllexport) TEST_STRUCT Test123();<br />
<br />
extern "C" __declspec(dllexport) TEST_STRUCT Test123()<br />
{<br />
TEST_STRUCT TestStruct;<br />
<br />
TestStruct.item[0] = 11; <br />
<br />
return TestStruct;<br />
}<br />
1. I agree with you on this.
2. I tried the <MarshalAs(UnmanagedType.ByValArray, SizeConst:=100)>, and it didn't work.
If I declare the bFound as int16 at the vb.net side, then I can get 0 or 1. But that's not what we need.
3. Please enlighten me on the IntPtr and Marshal.PtrToStringXxx methods, as I am still not sure how to use it in this case.
>>4. as long as one struct member isn't marshaled correctly, everything that follows it may fail.
>>so start by putting the string last!
4. I appreciate this advice. I will strictly follow this.
I still could not interop sName, bFound and item[100]. I am getting error message "Method's type signature is not PInvoke compatible."
Any help will be amazing...
cheers,
Goutam
|
|
|
|
|
Hi,
1.
yes ByValArray and SizeConst is what you need to pass an embedded array, here is a C# example:
struct XXX {
[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
public short[] array;
...
}
2.
I forgot to warn you about data sizes: most X86 native compilers consider long a 32-bit integer, so its managed counterpart is an int , not a long .
3.
There are additional marshaling fields for strings that I keep forgetting; they allow you to embed a string content (with fixed maximum length) into a struct. Here is an example, again in C#:
struct XXX {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string lfFaceName;
}
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Hi,
I am sorry to say that I am not making any progress. I wonder if my problem is some where else and I am touble shooting at some where else.
If I create an MFC Active X control, it automatically creates DllRegisterServer and DllUnregisterServer modules, to register to regedit by using regsvr32.
When I create this CLR dll, DllRegisterServer and DllUnregisterServer modules are not created automatically. And, I can't register this dll.
Is it a must to register a dll by using regsvr32?
Well, I am trying to look at the problem from other angels...just to make sure I am not missing anything.
cheers,
Goutam
|
|
|
|
|
Hi,
This is how I understood the DLL stuff:
- a managed code DLL gets referenced by a .NET project; it will either be copied into the EXE folder, or it must reside in the GAC;
- a native code DLL can be stored anywhere, Windows will look for it using the PATH system environment variable;
- a COM code DLL (which holds native code), needs to be registered.
When a .NET exe does not find a DLL it needs, IMO it clearly says so, with one proviso: when it says it is not finding XXX, it may well be it is not finding one of the dependencies of XXX.
I don't understand why you are doubting this, you already have parts of your struct being passed back and forth successfylly!?
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Hi,
I have an array, x = {10,20,30,"",""). I want the length of this array with non-empty fields, i.e. 3 instead of 5.
Also, I want to store the entries without Null in another array.
How to implement this in VB?
thanks
|
|
|
|
|
You'd be better to use a generic list. Then you can remove items at all.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Christian Graus wrote: You'd be better to use a generic list. Then you can remove items at all.
How to implement this in VB?
|
|
|
|
|
He asked this just yesterday I think.
I believe he even copy and pasted his query exactly as before.
|
|
|
|
|
|
Assuming you have a variable that holds how many items are in the array you can use the redim preserve commands.
redim preserve yourarray(number_of_items)
One warning though. Don't overuse this command because internally it creates a new array and copies all of the contents to the new array so if you call this too many times with large arrays it can make your program slow. Also if you resize arrays like this make sure you pass them byref not byval or else the changes won't be reflected in the calling function/sub.
modified on Thursday, November 12, 2009 10:57 PM
|
|
|
|
|
i have a table which i call "RATES" and it s
..............(column1)
..............rate_start....commission.....rate_finish
row 1
................300..............2.............500.....
................501..............3.............600.....
................601..............4.............700 ....
.......................................................
................1500 ............8.............1800....
user entry etc total.text="532" (if user entry is "532" then respond should be "3")
how can i find the correct "commission"
my query is not working right it s ;
"select commission from RATES where rate_start < "' total.text and rate_finish > VALUE ....
plz help me
|
|
|
|
|
plz let me know your own query do not try to fix my query
|
|
|
|
|
I assume this is homework. You should talk to your teacher if you are stuck, or read the books your class recommended.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
... WHERE rate_start <= " & total.text & " AND " & total.text & " <= rate_finish"
How hard can it be?
warnings:
1. you need <=
2. what if the user enters a bad number, e.g. -5?
3. what if the user enters a partial SQL command that would delete your tables?
Recommendations:
4. use PRE tags for a non-proportional font, as I did above.
5. extract, parse and validate your user input; do not directly enter user text into an SQL statement.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
I have this string "Name1 Name2 Name3" and want to split that a=Name1, b=Name2 and c=Name3. How to make this
|
|
|
|
|
congratulations. your subject line is very good. even Google understands it.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Given the existence of intellisense, how can someone even intuitively know the command they need, and still not find it ?
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Christian Graus wrote: how can someone ... not find it ?
That is a though one.
Luc Pattyn
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Dim x() as String
Dim str as String = "Name1 Name2 Name3"
x = str.Split(" ")
'Now x(0) will be Name1, x(1) will be Name2, etc.
|
|
|
|
|
|
Do some experimentations before asking for help. You store it in a "string" and you want to "split" it. Your question contains the clue in itself. Use the String.Split() method. .NET has made it very easy and intuitive to learn and to do programming. Yet, people keep asking such basic questions.
|
|
|
|
|
Hi,
I want to delete my sql database entries, i.e. delete all the rows of database "payments".
I have written this code:
Public Function DeletePayRecord()
cmd = New SqlCommand("Select * FROM payments", con)
If con.State = ConnectionState.Closed Then con.Open()
myDA = New SqlDataAdapter(cmd)
Dim myPayDeleteDataSet As New DataSet()
myDA.Fill(myPayDeleteDataSet, "payments")
For Each dr As DataRow In myPayDeleteDataSet.Tables("payments").Rows
dr.Delete()
Next
End Function
I found that my rows are not getting deleted. Please suggest me how to do this?
Thanks.
|
|
|
|
|
You're kind of taking the long way with what you have so far. You can use what you have and just add that you need to do an update back to the database...or you can start over and use a Delete SQL statement.
If you use the Delete SQL statment
DELETE * FROM payments
You don't even need a data adapter. Just run the command with an execute nonquery.
|
|
|
|