- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I need some help in the above subject.
I had made a standard dll for my C# developer. He is finding it difficult to call that from C# and all previous examples were involving strings. Ours involve real and integer type arrays.
He has also asked if I could supply him with a standard COM dll instead. He says it is easy to integrate .NET with COM instaed of standard Win32 dlls.
Basically, the question is how to import a particular subroutine from one of my dlls.
Following is the fortran Dll I created
I need some help in the above subject.
I had made a standard dll for my C# developer. He is finding it difficult to call that from C# and all previous examples were involving strings. Ours involve real and integer type arrays.
He has also asked if I could supply him with a standard COM dll instead. He says it is easy to integrate .NET with COM instaed of standard Win32 dlls.
Basically, the question is how to import a particular subroutine from one of my dlls.
Following is the fortran Dll I created
SUBROUTINE PDP(X,Y,W,M,P,N) ! Parison digitization(X,Y,W) -> P(*,7):S,RA,W,VOL,RI,RO,YA !DEC$ ATTRIBUTES DLLEXPORT :: PDP !DEC$ ATTRIBUTES C, ALIAS:'PDP' :: PDP use colorb ! to transfer value of S(9) contour length ! use pieval implicit none integer,Parameter:: M1=9 Real P(42,M1),X(M1),Y(M1),W(M1),S(M1),R(M1) ! P was (21,M) real GP,CI,PI3,FR,DS,SN,CS,WS,VV,DZ Integer I,J,N,L,K,M DATA GP,CI/2., -25.4/ PI3=PI/3 S(1)=0 DO 2 J=2,M ! M is now 9. Was 7 in earlier version I=J-1 R(J)=X(J)-W(J)/2. ! Middle of Preform Wall DS=SQRT((R(J)-R(I))**2+(Y(J)-Y(I))**2) ! Distance between Adj points IF(J.EQ.2) DS=.5*PI*R(2) ! A fourth of the quadrant perimeter S(J)=S(I)+DS ! Contour length P(1,J)=0. ! P(1, 1..8)=0 2 CONTINUE DZ=S(M)/(N-1) ! Divide total contour length into 20 equal segments, N is 20 P(1,1)=0. P(1,3)=W(1) R(1)=R(2) pf_ct_l=S(M) !to transfer value of contour length for CCGR routine I=1 DO 3 L=2,N K=L-1 P(L,1)=K*DZ ! P(1..20,1) are the new height locations J=I 4 J=J+1 IF(S(J).LT.P(L,1).AND.J.LT.M) GOTO 4 I=J-1 FR=(P(L,1)-S(I))/(S(J)-S(I)) ! fraction P(L,3)=W(I)+(W(J)-W(I))*FR !wall thickness at each location P(L,2)=R(I)+(R(J)-R(I))*FR ! outside radius at each location P(L,7)=Y(I)+FR*(Y(J)-Y(I)) ! Height at each location P(L,5)=(P(L,2)-.5*P(L,3)) ! Radius at midpoint P(L,6)=(P(L,2)+.5*P(L,3)) IF(J.LE.2) THEN SN=SIN(P(L,1)/R(2)) ! P(L,1)/R(2) is the angle and R(2)*Sin () is the x distance P(L,2)=R(2)*SN P(L,5)=(R(2)-.5*P(L,3))*SN P(L,6)=(R(2)+.5*P(L,3))*SN CS=SQRT(1-SN*SN) P(L,7)=Y(2)-R(2)*CS ENDIF WS=P(K,3)+P(L,3) VV=PI3*DZ*(P(K,2)*(P(K,3)+WS)+P(L,2)*(P(L,3)+WS)) P(L,4)=P(K,4)+VV 3 CONTINUE RETURN END SUBROUTINE PDP {/pre] Following is the dll import that he used in C#[DllImport("pdp_dll.dll")] public static extern void PDP([MarshalAs(UnmanagedType.LPArray)]ref float[] X, [MarshalAs(UnmanagedType.LPArray)]ref float[] Y, [MarshalAs(UnmanagedType.LPArray)]ref float[] W, [MarshalAs(UnmanagedType.I4)]ref int PN, [MarshalAs(UnmanagedType.LPArray)]ref float[,] PPP, [MarshalAs(UnmanagedType.I4)]ref int points); When I try to call the PDP method from code, with something like this: float[] X = new float[9]; X.Initialize(); float[] Y = new float[9]; Y.Initialize(); float[] W = new float[9]; W.Initialize(); float[,] PPP = new float[42,9]; PPP.Initialize(); try { int intLength = 9; int intPoints = 42; PDP(ref X, ref Y, ref W, ref intLength, ref PPP, ref intPoints); } catch (Exception ex) { MessageBox.Show(ex.Message); }
An ?Object reference not set to an instance of an object? exception is thrown. I believe this is a common error to occur if your DllImport statement does not match the method signature correctly.
Any help would be greatly appreciated.
Thanks
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could turn your subroutine into a COM server using the wizard in CVF Professional, but why? Your current approach should work and seems simpler.
Try breaking the problem into smaller parts -- for example just passing an int or an array of floats.
MarshalAs(UnmanagedType.I4) may be a problem. Fortran expects a pointer to a integer, not an integer. MarshalAs(UnmanagedType.LPArray) might work better.
Try breaking the problem into smaller parts -- for example just passing an int or an array of floats.
MarshalAs(UnmanagedType.I4) may be a problem. Fortran expects a pointer to a integer, not an integer. MarshalAs(UnmanagedType.LPArray) might work better.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks!
Can you show me a little example of how to turn this into a COM server. I am probably trying something way out of my league but an example would be helpful. I looked at all the sample examples under advanced/com. Is there one that is closer to my case that I can study.
My C# developer told me that ".NET creates interop dlls automatically for working with COM objects, so there is usually no problem with having to figure out calling conventions" and also that" you can?t use LPArray on an integer. Also, the fact that I have declared the integers to be passed by reference IS a pointer, which he mentions Fortran is expecting "
It is not my idea to put one against the other but any solution in either way would be very much appreciated.
Thanks
Can you show me a little example of how to turn this into a COM server. I am probably trying something way out of my league but an example would be helpful. I looked at all the sample examples under advanced/com. Is there one that is closer to my case that I can study.
My C# developer told me that ".NET creates interop dlls automatically for working with COM objects, so there is usually no problem with having to figure out calling conventions" and also that" you can?t use LPArray on an integer. Also, the fact that I have declared the integers to be passed by reference IS a pointer, which he mentions Fortran is expecting "
It is not my idea to put one against the other but any solution in either way would be very much appreciated.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran with the "C" calling convention expects integers and floats to be passed by value and arrays to be passed by reference. Try the following:
public static extern void Hello(float[] X, float[] Y, float[] W, int PN, float[,] PPP, int points);
and
Hello(X, Y, W, intLength, PPP, intPoints);
This uses P/Invoke's default marshalling, which should correctly pass your int's and arrays in and return values from the arrays.
public static extern void Hello(float[] X, float[] Y, float[] W, int PN, float[,] PPP, int points);
and
Hello(X, Y, W, intLength, PPP, intPoints);
This uses P/Invoke's default marshalling, which should correctly pass your int's and arrays in and return values from the arrays.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Many Thanks for your help.
My C# developer says it seems to work now.
I may have some more questions later on.
Thanks again
Sumit
My C# developer says it seems to work now.
I may have some more questions later on.
Thanks again
Sumit

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page