I am trying to figure out what I can use in visual basic .net that would act similar to this
http://docs.xojo.com/index.php/MemoryBlock
Thank you
You can either use an array Byte() or List(Of Byte), or manipulate memory directly with the System.Runtime.InteropServices.Marshal class's .AllocHGlobal method with IntPtr. Note that VB.NET does not allow for pointer arithmetic like C# does. A common workaround is to use Marshal to copy memory from an address into a Byte array, perform the work there, then copy it back to the original address.
But we need more information about your ultimate intent. I want to avoid an "XY Problem".
Related
Where in the VB6/VBA project references do Array(), LBound(), and UBound() come from..? When I'm typing in code, they don't appear in the Autocomplete list (ctrl+space), they don't get autocompleted, and they must be typed out completely before the text editor recognizes them. And only when a left-parenthesis is typed will ToolTipText pop up with the command syntax. Also, they do not appear anywhere in Object Explorer.
There's probably a basic concept in play here that I'm not aware of. And it makes me wonder, what other commands/statements/keywords are hidden in the same way..? Is there a list somewhere..? I googled for info but didn't find anything, probably because I don't know what I'm looking for and using the wrong search terms.
I ask these questions because I have the habit of prefixing many VB6 built-in functions like this: VBA.Left(), VBA.Len, VBA.Instr(), and so on. But I can't figure out what reference prefeix to use with Array(), LBound(), and UBound(), or perhaps they're so basic to VB6 that they don't have one.
I do this prefixing because years ago I was working on a large project, and there were functions I was trying to use with the same name in different reference libraries. I was a newbie and it took me a while to figure out, and it was causing tremendous problems since the functions were just NOT working the way I thought they were supposed to. It was then that I developed the prefixing habit after I figured it out. It's just easier that way, and always ensures the expected functions are being used.
The reason that they don't appear as IntelliSense options (and also why they don't appear in the Object Browser) is that they aren't declared in the VBE7.dll typelib for some reason that's beyond me. The Array function is implemented in the .dll as rtcArray. The utility of knowing that is dubious, in that its sole argument is a ParamArray, which means that if you called it directly from VBE7.dll you would need to create an array to have it feed you back the same array... This partially explains why it isn't on the typelib - a COM call would need to do the same thing, and the marshaling would basically be doing the same thing as what you'd expect the function to return.
LBound and UBound don't even appear as functions in the export table, so my guess is that they are handled more like "keywords" than first class functions internally. This makes some sense, in that it's fairly trivial to check the bounds of a SAFEARRAY if you have a pointer to the automation struct (you just index into the rgsabound array at the end of it and read the cElements and lLbound from it. Again a guess, but I'd assume that this allows for flexibility in letting LBound and UBound function with both fixed length and variable length arrays. In the fixed case, the array is basically managed as a block of memory with an indexer (more like a VT_CARRAY than a VT_SAFEARRAY). I'd imagine that handling this internally was easier or more convenient than providing first-class functions.
You won't find Debug in the Object Browser either, nor its methods Assert and Print.
You won't find Statements that are used like methods, like Open, Close, Get and Put, which is why you don't get any Intellisense when you use those statements, and the syntax must be memorized.
You will find Load and Unload as members of VBA.Global, but it's not clear what they belong to otherwise, and their arguments are late-bound Objects. The VBA documentation states that Load and Unload are Statements, even though the Object Browser shows them as Methods.
Keep in mind that you can move the order of references and it will make a difference. Try moving VBA to the top or near the top of your list of references. I believe that if something else also defines a BASIC keyword, it steals it, in a sense. I once had Right disappear and because I was not aware of the order of references, had to change all references of Right to VBA.Right. It's possibly the same with the ubound, lbound, or array.
I have 3rd party lib that controls camera.
It is written in C++ and I want to consume it from C#. The lib grabs image as byte*.
There are some ways to pass this to C#.
Pass byte* directly to C# with unsafe statement. In this case, C# code can't change image size like crop operation.
Use Marshal.Copy to create managed byte array and pass it. This gives flexibility to C#, but there is overhead and additional memory usage.
So, my question is:
Is there a way to convert byte* to managed byte[] without copy? Because managed byte array with fixed statement is "blittable", I think there can be "reverse direction" method.
Any help is appreciated, thank you.
After working some time in VB.NET I would like to get rid of Microsoft.VisualBasic dependencies.
Since with text files and string manipulation goes easy here I don't know what to do.
Is it possible to write equivalent code in VB.NET without using Microsoft.VisualBasic namespace and how this code should look like?
Dim fnum As Integer = FreeFile()
FileOpen(fnum, "Setup\myadmin", OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(idstruct))
FilePut(fnum, idstruct, 1) 'structure data to file in record 1
FileClose(fnum)
As much as I sympathise with your desire to remove all references to the Microsoft.VisualBasic namespace, and as much as I think that doing so has value, sometimes it's just not worth the trouble. The namespace does contain some useful tools which are not easily reproduced without it.
For instance, the TextFieldParser comes to mind. It allows you to easily read CSV and fixed-width files. There is no other class like it in the .NET framework. So, is it worth it to reinvent the wheel just so that you don't reference the Microsoft.VisualBasic namespace? I would argue that it's not worth it.
While it would be possible to reproduce the behavior of FileGet and FilePut using FileStream and the StreamReader, StreamWriter, BinaryReader, and BinaryWriter classes, it's probably not worth all the trouble. The FileGet and FilePut methods are provided specifically for backwards compatibility, so if compatibility with old systems is your goal, as much as it pains me to say it, using FileGet and FilePut is an appropriate solution.
However, some of this advice hinges on the type of data. If, for instance, the structure only contains fixed width strings, that would be very easy to duplicate with the StreamReader and StreamWriter, or with the TextFieldParser. Or, if it contains just integers, perhaps it will be easy to reproduce with the BinaryReader and BinaryWriter.
However, even if you can easily reproduce the logic using other non-VB-only classes, doing so doesn't gain you anything. In fact, your code will be more complicated and it will be less self-documenting. When you see code using FileGet and FilePut, not only is it easy to tell what is being done, but it is also obvious that it is for backwards compatibility. If you replace them with your own logic, the necessity for backwards compatibility would not be obvious without adding comments to the code.
If you don't like looking at them, which I can certainly understand, it may be worth wrapping them in a wrapper class. For instance, you could create a data-access style class with load/save methods which internally just use FileGet and FilePut. Doing so would be good practice anyway. That way, if you ever choose to store the data in a different format, or a different data source (such as a database), you could change it in the one class without having to rewrite all of your code.
One other thing I've just found is this MSDN page about My.Computer.FileSystem:
http://msdn.microsoft.com/en-us/library/0b485hf7%28v=vs.90%29.aspx
which I found was referred to from the MSDN page on FilePut:
http://msdn.microsoft.com/en-us/library/0s9sa1ab%28v=vs.90%29.aspx
From posts like this one It's my understanding that it's just a wrapper for System.IO anyway, but it supposedly provides a "more convenient and understandable" interface to the underlying IO functions.
If you're referring to your use of the LEN() function (which is the only thing I can see that refers to Microsoft.VisualBasic namespace, unless I'm missing something), then you can just use String.Length instead. E.g. idstruct.Length, assuming idstruct is a String.
Look at System.IO.FileStream. The approach is a bit different, but it is quite simple.
Dim fs As New FileStream(mUserFile, FileMode.XXX, FileAccess.XXX)
or:
Using fs as New FileStream....
End Using
The main thing that will change is that rather than writing a structure, you would convert it to an array of bytes (Count would be the length of your array, offset 0 in your example):
fs.Write(byt(), lOffset, lCount)
You COULD wrap it all up in a class to emulate the old random access file method if there it a lot of legacy code to support. There is also a BinaryReader and BinaryWriter and you could also look into serialization if the data is large but mostly static.
I have an application that involves a lot of communication between managed (C#) and unmanaged (C++) code. We are using Visual Studio 2005 (!), and we use the interop assembly generated automatically by tlbimp.
We have fairly good luck passing simple structs back and forth as function arguments. And because our objects are fairly simple, we can pack them into SAFEARRAYs using the IRecordInfo interface. Passing these arrays as arguments to COM methods seems to work properly.
We would like to be able to embed variable-length arrays in our UDTs, but this fails badly. I don't think I have been able to find a single piece of documentation showing how someone has accomplished this. Nor have I found documentation that says it can't be done.
1) Naive approach: Simply declare a safearray in the managed code:
struct MyUdt {
int member1;
BSTR member2;
SAFEARRAY *m3;
};
The C++ compiler is happy with this, but the generated IDL confounds tblimp.exe. It reports that it is unable to convert the signature for member m3, and the signature for member tagSAFEARRAY.rgsabound. These are only warnings, but they are meaningful, the resulting assembly is not usable.
Using LPSAFEARRAY, oddly enough, fails in different ways, but for the same reason, tblimp just can't deal with it.
2) Trickier: Pack it into a variant:
struct MyUdt {
int member1;
BSTR member2;
VARIANT m3;
};
We have code that builds safearrays of UDTs, and it never gives us any trouble. It's basically copied from MSDN. Using that code to create a safearray, then:
pVal->m3.vt = VT_SAFEARRAY | VT_RECORD;
pval->parray = p;
Fails in odd ways. It always breaks, some variations produce an OutOFMemoryException... odd, others fail in different ways. (I'm not sure if a pRecInfo pointer is required here or not, but it fails the same way, present or not.)
The Google search space for this is badly polluted with answers to questions that I am not asking:
How do you pass UDT/structs from unmanaged code.
How do you pass a SAFEARRAY of structs? (We're doing this fine.)
How do you use p/invoke or customer marshalling to pass UDTs.
And many answers describing how to define things from the managed side, not the unmanaged side.
And then there are a couple of Microsoft KBs describing problems with VT_RECORD in early versions of .NET. I don't think these are germane - VT_RECORD types work with VARIANT and with SAFEARRAY. (But maybe not with the UDT marshallling...)
If this won't ever work, it would be nice to at least know why.
Mark
I have a module A in Managed C++, it depends on module B in native C++ which wrapped as COM plus.
In module B, I read bytes from a file. Now I am trying to call the file reading functionality from A. But failed.
Dependency detail: I used tlbimp.exe and generated the interop according to Module B. A referrs to the interop.
I tried to pass an "array^" but only one char was received, which is understandable because marshaling doesn't know the array length and could NOT handle the whole array.
I searched out some recommendation about safe array, but could NOT use it successfully in my projects.
Could somebody help me on this?
Thanks a lot.
If you are going to be talking to your native object via COM, you're going to have to pass the array the COM way.
SAFEARRAY would definitely work, but you don't have to use it. It is a fair amount of work to set up anyway. If neither component is a scripting language or VB6, there is little value to using a SAFEARAY.
COM can marshal the array just fine, you just have to tell it how big it is. The two most common mechanisms in COM to pass (native) arrays are "fixed-sized arrays" and "conformant arrays".
Fixed-size array:
If you know at compile time the size of the array, this is the way to go. Declare your COM method as follows in your IDL:
...
const long ARRAY_SIZE = 1024;
...
HRESULTS MethodAbc(MyClass array[ARRAY_SIZE]);
Marshalling will take care of passing the whole array.
Conformant Arrays:
You declare them as follows in IDL:
HRESULT MethodAbc([size_is(arraySize)] MyClass array[], long arraySize);
This tells COM that the arraySize parameter holds the count of elements.
My experience with CLI is minimal, but I don't think you can just pass a CLI handle. Among other things, I believe you need to pin the pointer so that GC doesn't move the array during the COM call. Others please correct me here if I'm wrong.