|
Hi All
I wonder if any one can help me figure out (or just plain tell me) how to make changes to an unmanaged struct created by a C++ DLL from VB.NET.
I think I understand how to make a copy of it, and then makes changes to the copy.
The structure in VB (which matches the unmanaged struct created from the C++ DLL) is:
<StructLayout(LayoutKind.Sequential)> _
Public Structure passedStruct
<MarshalAs(UnmanagedType.U4)> Dim IntNumber As UInt32
<MarshalAs(UnmanagedType.U4)> Dim IntAnother As UInt32
<MarshalAs(UnmanagedType.U4)> Dim ptr2Integer As UInt32
End Structure
I call a function in the C++ DLL that creates a version of the struct, populates it, and returns the ptr to it. I can then make a copy just by something like:
Dim receivedStruct As passedStruct = Marshal.PtrToStructure(ptr, GetType(passedStruct))
This works fine and I can even pass the pointer of the copy back to the C++ DLL and have changes made from the DLL.
However, I'd like to do this the other way around to. I would like for the VB.NET application to receive the pointer from the C++ DLL and then make changes directly to the unmanaged version of the struct rather than making a copy of it. In C++ this is pretty easy, for example:
extern "C" __declspec(dllexport) void ChangeStruct(struct MyStruct * pMyStruct)
{
pMyStruct->IntNumber += 23;
}
which just receives the pointer from VB.NET of a structure created in VB.NET and makes changes to it directly. MyStruct is defined as:
struct MyStruct {
unsigned int IntNumber;
unsigned int IntAnother;
unsigned int IntYetAnother;
};
Does anyone know how to do this same thing in VB.NET?
Many thanks indeed for your assistance.
Kurt
|
|
|
|
|
Hi,
I haven't done any interop from VB.NET, but I did a lot of P/Invoke from C#.
I tend not to allocate stuff in the unmanaged world, let the managed world allocate its
own things, then try and have the native world just access those.
This is what I would try, without a single copy, and without Marshal.PtrToStructure:
- allocate the struct in the managed world
- pass it by reference
- in the unmanaged world accept it as a struct pointer, and read and modify at will
- back in the managed world, see how the structs content has changed, without having made a single copy anywhere.
BTW: IMO you can throw away most of the Marshal attributes, you don't need most of them.
e.g. <marshalas(unmanagedtype.u4)> is the default for UInt32
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Thanks Luc - that is kinda what I'm doing at the moment, and it works fine. Thanks for pointing out my overcautious useage of <marshallas...> - a good sign that I don't really know what I'm going
It is not clear to me why I really need to be able to change the C++ DLL created struct. The arguement that has been given to me is that the C++ developer does not want to make changes to the C++ library to deal with interacting with VB.NET as he wants it to use the code as is for Linux applications to. He also does not want to have a scenario whereby if the DLL is changed the application would have to be changed. Whereas I argue that I at least have to create a .NET wrapper DLL to use the functions and therefore will have to at least make changes to function names if they are changed - hardly a big bother (esp. as it enables me to work in .NET!).
Anyway, the library is for accessing a custom card on the PCI bus. When I call the function that updates the firmware on the card, it creates an struct that contains the various parameters that are needed to define a particular card. Most of these details come from the system, and only a few from the .NET application. I figured that an easy (although not exactly lean) approach would be to simply include the various card details in the call to the DLL function. However this would mean having a different function for the .NET DLL than as for the Linux DLL - i.e., more work for the C++ developer... apparently. If I'd been writing the control application in C++ then apparently I could easily import the class in the DLL and simply use the 'new' keyword to create new card struct objects. As the DLL is not COM or .NET compatible I don't believe I can do that and hence all this back and forth with the two copies of the struct.
Although I see no issue with the struct being created in the managed world (the .NET app) and then passing the pointer to the unmanaged world (the C++ DLL) (as you suggest), I'd like to be able to do it the other way around if possible... if nothing else it is some knowledge that might prove useful one day.
Many thanks, Kurt
|
|
|
|
|
Hi Kurt,
if you insist on having a native struct manipulated by the managed world without actually copying the data into a managed struct, the only way I can see is by going the unsafe way, with pointers, pointer manipulations, and all the niceties C/C++ offers and the managed languages normally are shielding you from.
In C# that would take an "/unsafe" compiler switch, an unsafe{...} code block,
some pointer (say a int* myIntPointer; ) and from then on it looks and smells very much like C code.
With that kind of code, any time the DLL changes, your wrapper is open for big trouble. I would suggest, if not already present, the DLL offers an int getVersion() returning a new and higher number after each code modification, so you can check for mismatches before dereferencing pointers and digging in struct members.
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
|
|
|
|
|
Hmmm... sounds like a can of worms I'd rather avoid opening
|
|
|
|
|
Hi,
I'm currently working on a program that automaticly adds pictureboxes whenever you add an entree to a database (access).
I got that working, but Now I'm wondering how you make the picturebox (or whatever) ask where the image is located to draw it in the picturebox.
Example:
Database:
tblAnimals contains
- Dog
- Cat
Now in my form it auto adds 2 pictureboxes without containing any images. Now it should ask for the image location (C/Document/Pictures/Dog.jpg) and draw that in the picturebox.
I have no idea how to this, anyone has any ideas?
Already thx
This is my code now:
Dim bytTeller As Byte
Dim objdtsProducten As New dtsProducten
Dim objtblProductenTA As New dtsProductenTableAdapters.tblProductenTableAdapter
Dim dtrProduct As dtsProducten.tblProductenRow
objtblProductenTA.Fill(objdtsProducten.tblProducten)
For Each dtrProduct In objdtsProducten.tblProducten
Dim ptbKnop As New PictureBox
ptbKnop.Name = dtrProduct.ProductID
ptbKnop.Text = dtrProduct.ProductNaam
ptbKnop.Size = New Size(80, 40)
ptbKnop.Location = New Point((bytTeller Mod 4) * 90, (bytTeller \ 4) * 50)
AddHandler ptbKnop.Click, AddressOf KnopGeklikt
Me.Controls.Add(ptbKnop)
bytTeller += 1
Next
I know I can open a picture with this:
With OpenFileDialog1
.CheckFileExists = True
.ShowReadOnly = False
.Filter = "All Files|*.*|Bitmap Files (*)|*.bmp;*.gif;*.jpg"
.FilterIndex = 2
If .ShowDialog = DialogResult.OK Then
' Load the specified file into a PictureBox control.
Dog.Image = Image.FromFile(.FileName)
End If
End With
But I don't know the name of the picture yet (see DOG)
modified on Friday, March 13, 2009 3:24 PM
|
|
|
|
|
What do you mean by "name of the picture"?? Are you trying to ask the user what the content of the image is?? If so, you just create a small form with a textbox on it and show that to get the users description.
|
|
|
|
|
I` AM LOOKIING FOR A PROGRAMMER TO DEVELEP SOME SMALL PROGRAMES
WITH BIOMETRIC PROGRAMS
BIOMETRIC PROGRAM
-----------------
FACE RECOGNITION
FINGER RECOGNITION
EYE LID RECOGNITION
HEAD MOVEMENT RECOGNITION
THEY ARE ANOTHER 20 SMALL PROJETS IN THE PIPE LINE LIKE
-------------------------------------------------------
OBJECT RECOGNITION
VOICE RECOGNITION
AI
COMMAND RECOGNITION
USB / COM AND RS232 INTERFACING
PRICE NEGOTIABLE
IF YOU WAN TO KNOW MORE PHONE ME AT 07984332015
MY EMAIL IS leeds_leisure@hotmail.co.uk
|
|
|
|
|
Right Place[^]
TVMU^P[[IGIOQHG^JSH`A#@`RFJ\c^JPL>;"[,*/|+&WLEZGc`AFXc!L
%^]*IRXD#@GKCQ`R\^SF_WcHbORY87֦ʻ6ϣN8ȤBcRAV\Z^&SU~%CSWQ@#2
W_AD`EPABIKRDFVS)EVLQK)JKSQXUFYK[M`UKs*$GwU#(QDXBER@CBN%
Rs0~53%eYrd8mt^7Z6]iTF+(EWfJ9zaK-iTV.C\y<pjxsg-b$f4ia>
--------------------------------------------------------
128 bit encrypted signature, crack if you can
|
|
|
|
|
You've come to the wrong place. We help people write their own code. We don't write it for you.
If you want someone to write an app for you, check out RentACoder.com.
|
|
|
|
|
Oh, and "Object Recognition", "AI", "Voice Recognition", "Face Recognition", ... are NOT small projects. Get out your checkbook becuase these apps take teams of people and they are not cheap. Some of the stuff you're talking about are still nothing more than research technologies and don't work very well in the real world, yet.
|
|
|
|
|
I notice you pointed him to rentacoder and not the CP Job Board ?
And yes, this is hilarious. Small projects indeed....
Christian Graus
Driven to the arms of OSX by Vista.
|
|
|
|
|
Christian Graus wrote: And yes, this is hilarious. Small projects indeed....
Now you know why I didn't point him at the job board. Someone who thinks those projects are "small" really doesn't have a grasp of what it takes to do them. So why put anyone here through the pain of dealing with a bad client?
|
|
|
|
|
WRITING IN CAPITAL LETTER IS THE TEXTUAL VARIANT OF SHOUTING!!
(Just to be clear, it's considered rude.)
I are troll
|
|
|
|
|
Oh, look! A phone number (mobile, no less - people can reach you on the move) and an email address. I've got half a mind to post the email address and phone number to every spam mailing list I can think of, just to teach a lesson. First name of "Don't", middle name of "Spam", last name of "CodeProject!"
|
|
|
|
|
Make your program analyze my footprint as I kick you the heck out of these forums!
Any suggestions, ideas, or 'constructive criticism' are always welcome.
"There's no such thing as a stupid question, only stupid people." - Mr. Garrison
|
|
|
|
|
|
carlhaley wrote: leeds_leisure@hotmail.co.uk
See, normally, as an admin, I would delete your email address on the basis that you should use the paid job boards to advertise a job. But, in this case, I see no need, because you're a real moron, and you're not going to find what you want. You want one person to create these 'simple' projects. Anyone who stands an ounce of a chance at writing this stuff will note that:
1 - you are totally clueless as to what you're asking for and
2 - as you choose to spam the boards rather than pay for a job ad, you plainly don't have the money to pay for this work to be done
in which case, anyone who answers you, deserves you as much as you deserve them.
Oh, and I copied your email so you get even more spam from people trawling the web for email addresses. Enjoy your russian bride and your ciallis pills.
Christian Graus
Driven to the arms of OSX by Vista.
|
|
|
|
|
carlhaley wrote: leeds_leisure@hotmail.co.uk
Why stop at just his email address? I can think of a lot of people who would pay a few cents to have his number on their cold-calling lists
|
|
|
|
|
I think he is kidding us ...
|
|
|
|
|
hi guys,
i am developing an application which uses access mdb files as database.
untill now i used a connection to the files,
using the following code:
Public Class DBconnector
Private _dbConnection As OleDbConnection
Private _dbCommand As OleDbCommand
Private _dbDataReader As OleDbDataReader
Private _dbDataAdapter As OleDbDataAdapter
Private _dbTransaction As OleDbTransaction
'Private _dbADODBConnection As ADODB.
Public Sub New(ByVal cs As String)
_dbConnection = New OleDbConnection(cs)
_dbCommand = _dbConnection.CreateCommand
End Sub
where the connection string is:
"Provider=Microsoft.Jet.OLEDB.4.0;"
& "Data Source=" & TextEditPath.Text
texteditpath is the file path and name.
recently i have encountered an error while trying to create a relationship using "ON DELETE CASCADE" in the constraint clause.
error mentioned theres a syntax error on the constraint clause and there was no real syntax error , after troling microsoft forums , they have told me i need to use ADO connection because this bug results cause of use in DAO ,
my question is how do i establish an ADO connection to access MDB file
you can see my discussion in the ms forums here:
http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx?pg=2&cat=en_us_328f8dd6-f51c-496e-93d7-5d47a17e195c&lang=en&cr=us&guid=&sloc=en-us&dg=microsoft.public.access.queries&fltr=[^]
under the title : "add constraint return syntax error"
Net
|
|
|
|
|
This is a question for the General Database forum...
Did the command line to test the command work in Access 2007 in the Immediate window??
And you're already using ADO.NET. Using DAO (really, really, really old!) never happens in VB.NET unless you go out of your way to explicitly add DAO to the project and write the code to use it.
|
|
|
|
|
yes,
in the command line the Query works
im executing the following query:
CurrentProject.Connection.Execute "ALTER TABLE Holiday ADD CONSTRAINT CalendarHoliday FOREIGN KEY ([calendarid]) REFERENCES Calendar ([id]) ON DELETE CASCADE"
although in the SQL designer window of access 2007
the following query wont work:
ALTER TABLE Holiday ADD CONSTRAINT CalendarHoliday FOREIGN KEY ([calendarid]) REFERENCES Calendar ([id])
generate same error as i get in the oleDB connector withing the .net framework:
syntax error in constrain calause
i dont know how to set a connection to the file so this query will work as it works in the immidiate window
Net
|
|
|
|
|
mistake in my post the sql in design window is:
ALTER TABLE Holiday ADD CONSTRAINT CalendarHoliday FOREIGN KEY ([calendarid]) REFERENCES Calendar ([id]) ON DELETE CASCADE
Net
|
|
|
|
|
If you want to establish an ADO connection to an Access MDB file in .NET, you will need to use COM Interop and start by setting a reference to Microsoft's ActiveX Data Objects library. This comes up often, and I guarantee if you google activex data objects "Com Interop" you will find examples.
|
|
|
|