|
That is not how things get done normally in a managed application. Arrays are objects, hence allocated on the heap (one of the heaps actually, yours will be the "large object heap"). To allocate on the stack you would need the "stackalloc" keyword, which is not a good idea most of the time.
I strongly recommend you allocate all arrays on the managed side and pass them to the native/Fortran world as indicated in my article.
|
|
|
|
|
I am allocating all the arrays on the C# side, and they are all 1D arrays. What I am not doing is using the fixed keyword or the GCHandle class as outlined in your article. Do you think one of these techniques might solve my problem. I can test it out when I get to work on Monday.
|
|
|
|
|
if you have to go from C# to native, you need a pointer value; you simply cannot get a pointer value without using either fixed or GCHandle, unless you trust the automatic marshaling which AFAIK will allocate another array and copy all the data, something I never want to happen as it brings nothing (it doubles the memory footprint, wastes CPU cycles and trashes the caches).
|
|
|
|
|
OK, I did not realize there could be a problem with the pointers. As I have mentioned, the code works when passing small arrays. As a new C# programmer, I copied my interface to the DLL from existing code used at our company. I am fairly certain these other codes only pass relatively small arrays compared to what I will need to pass.
I see now that there are some fundamentals that I don't understand, such as automatic marshaling. Your "copy all the data" observation does not sound good. I always assumed that when I passed in an array, I was passing in a pointer. But from your article, it seems that this pointer can get moved around, and not be reliable? I have to put in more study time on this.
I am looking forward to testing yuor ideas on Monday.
I hope you understand that from the point of view of 34 years of Fortran programming, this is a headache. However, I understand the benefits to be gained by converting to a C# interface for our modeling subroutines. It is unfortunate that we don't have the resourses to convert all the Fortran, and eliminate the DLL.
|
|
|
|
|
Yes, the garbage collector "GC" (part of which runs on its own thread) may move around objects, and does so asynchronously to your own code execution; the managed world knows how to deal with that, unmanaged code does not. By using fixed or GCHandleType.Pinned you prevent such moves.
Warning: pinned objects temporarily reduce the GC's capabilities, so you should not keep objects pinned longer than necessary.
I suspect your code currently works for small arrays and not for larger ones because the automatic marshaling is somehow limited (maybe it does allocate a temp array on stack??); I do not know any details as I try to not rely on it (I do trust it when strings are involved and an ASCII/Unicode conversion may be in order).
I have been marshaling arrays of 100MB+ without any problem; once you get the hang of it, it works like a charm. I have lots of code in C (and SIMD assembly) that gets called to operate on managed objects, such as huge images.
|
|
|
|
|
Hi Luc,
Luc Pattyn wrote: AFAIK will allocate another array and copy all the data
Interesting - A problem in an untested part of my code waiting to happen, you may have just saved me many hours of head scratching! Do you have a source for this? (about to google now!)
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
DaveyM69 wrote: Do you have a source for this?
I don't. The automatic marshaling, if it works, has to do something to protect native code against dangling pointers. I think I could devise a setup that proves me right or wrong. I might do that today...
|
|
|
|
|
Unless it copies everything (including all elements) by reference then it doesn't appear to create a copy.
I created a test C++ function that takes an array of ints as a parameter and I incremented all elements in the array. When I called this from C# and checked the values afterwards, all had been incremented - so it seems that the array is simply marshalled by reference (as I would expect as System.Array is a class) from managed to unmanaged.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
right.
|
|
|
|
|
Hi Dave,
sorry, I was wrong. My latest experiment[^] tells me automatic marshaling works fine.
There typically is no need to use unsafe and fixed keywords for passing arrays from managed to unmanaged world; only when the pointer(s) are kept around after the function returns, they may become invalid and GCHandle should be used.
|
|
|
|
|
are you using stackalloc ? don't.
are you using P/Invoke and DllImport ? if so, this[^] may help.
|
|
|
|
|
I am using DLLImport. I will check out your link.
|
|
|
|
|
Hi spainchaud,
sorry, I was wrong. My latest experiment[^] tells me automatic marshaling works fine.
There typically is no need to use unsafe and fixed keywords for passing arrays from managed to unmanaged world; only when the pointer(s) are kept around after the function returns, they may become invalid and GCHandle should be used.
|
|
|
|
|
I guess I will just have to put som more thought into my problem. Usually I come up with a solution, but it can take days to figure out some problems.
|
|
|
|
|
I have solved the problem. Thanks for everyone's help. The hint to the solution was the Wikipedia article on how to create a stack overflow. The example code they gave was:
int main(void) {
double n[10000000];
return 0;
}
When I got to work today, and started tracing the overflow, I found this code in my Fortran DLL.
COMPLEX*16 hxx(nstep*nrec*ntrn), hxy(nstep*nrec*ntrn), hxz(nstep*nrec*ntrn)
COMPLEX*16 hyx(nstep*nrec*ntrn), hyy(nstep*nrec*ntrn), hyz(nstep*nrec*ntrn)
COMPLEX*16 hzx(nstep*nrec*ntrn), hzy(nstep*nrec*ntrn), hzz(nstep*nrec*ntrn)
I realized I was putting these huge arrays on the stack. My new working code is:
COMPLEX*16, ALLOCATABLE :: hxx(:), hxy(:), hxz(:)
COMPLEX*16, ALLOCATABLE :: hyx(:), hyy(:), hyz(:)
COMPLEX*16, ALLOCATABLE :: hzx(:), hzy(:), hzz(:)
ALLOCATE(hxx(nstep*nrec*ntrn), hxy(nstep*nrec*ntrn), hxz(nstep*nrec*ntrn))
ALLOCATE(hyx(nstep*nrec*ntrn), hyy(nstep*nrec*ntrn), hyz(nstep*nrec*ntrn))
ALLOCATE(hzx(nstep*nrec*ntrn), hzy(nstep*nrec*ntrn), hzz(nstep*nrec*ntrn))
Thanks to the discussions here, I found the problem very quickly.
|
|
|
|
|
Hi all,
Hope someone can point me in the right direction.
I have a foreach loop that is pinging each COM port for a valid device that may be connected. I will eventually put this in a try-catch, but for now I'm just trying to determine how to create an array based upon the loop and then return that array to be used for generating a collection in a list box. Please see the code below: Also, a generic question...can a function return different data types eg. string, double, etc.
private string[] GetSerialDevice()
{
strPorts = SerialPort.GetPortNames();
foreach (string strPort in strPorts)
{
serialPort1 = new SerialPort(strPort, 115200, Parity.None, 8, StopBits.One);
serialPort1.Handshake = Handshake.None;
serialPort1.Close();
serialPort1.ReadTimeout = 500;
serialPort1.WriteTimeout = 500;
serialPort1.Open();
serialPort1.WriteLine("!001:USR1?\r");
string strUSR1Return = serialPort1.ReadTo("\r");
if (strUSR1Return == "+2.000000")
{
serialPort1.WriteLine("!001:SERL?\r");
string strSerialLow = serialPort1.ReadTo("\r");
serialPort1.WriteLine("!001:SERH?\r");
string strSerialHigh = serialPort1.ReadTo("\r");
double dblSerialNumber = double.Parse(strSerialHigh) * 65536 + double.Parse(strSerialLow);
Console.WriteLine("On" + " " + strPort + " " + "there is a valid amplifier with S/N "
+ dblSerialNumber.ToString());
}
}
serialPort1.Close();
return strPorts;
|
|
|
|
|
mprice214 wrote: can a function return different data types eg. string, double, etc.
yes why not.
What is your question ?
I am not getting exactly.
can you please more elaborate ?
Thank you
Life's Like a mirror. Smile at it & it smiles back at you.- P Pilgrim
So Smile Please
|
|
|
|
|
GetSerialDevice() at the moment returns a string array "strPorts". This is straight forward to me. If I have multiple devices connected to multiple COM ports, in the if loop inside the foreach loop, the double dblSerialNumber would generate a double for each device that is connected to the COM ports. What I don't know how to do would be to have dblSerialNumber as an array which would be made up of each dblSerialNumber that is generated by each pass of the foreach loop. Does that help?
|
|
|
|
|
You can use a Generic List or a Collection instead of an array and then use its Add method.
mprice214 wrote: can a function return different data types eg. string, double, etc.
A single method, no. You can have out parameters to return multiple values from a method.
|
|
|
|
|
I'm not familiar with that, but will look into it.
|
|
|
|
|
mprice214 wrote: return that array
Don't. Create a List and use its AsReadOnly property to return an IList.
|
|
|
|
|
PIEBALDconsult wrote: Don't. Create a List and use its AsReadOnly property to return an IList.
Can you elaborate as to why this would be better?
|
|
|
|
|
|
In two sentences or less?
|
|
|
|
|
I googled and binged and asked, but could not a find a perfect example on how to do this.
So, I gave it all I had.
I am trying to watermark a FLV video. I came across a forum that said you can use ffmpeg to do it. So, I looked around and got an idea of what I was going to do to get this to work.
The problem is that the below code does not work. Meaning that it does not watermark an image.
Process process = new Process();<br />
process.StartInfo.UseShellExecute = false;<br />
process.StartInfo.RedirectStandardInput = true;<br />
process.StartInfo.RedirectStandardError = true;<br />
process.StartInfo.CreateNoWindow = true;<br />
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;<br />
process.StartInfo.FileName = "C:\ffmpeg\ffmpeg.exe";<br />
process.StartInfo.Arguments = "ffmpeg -y -i ‘C:\video.flv’ -vhook ‘C:\ffmpeg\ffmpeg.exe' -f C:\Image.gif";<br />
process.Start();<br />
Thanks,
Harsimran Singh
1) The good news about computers is that they do what you tell them to do. The bad news is that they do what you tell them to do. - Ted Nelson
2) Why is it drug addicts and computer afficionados are both called users? - Clifford Stoll
3) The real danger is not that computers will begin to think like men, but that men will begin to think like computers. - Sydney J. Harris
(Computer code: 00001111 - translation: Hello! :P )
REMEMBER:
"Computers are made for us, we are not made for th
|
|
|
|