Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Fortran Programming Language

strange arguments passing problem (from vba to fortran dll)


Dear all,

I encounter a strange problem when I am trying to pass arguments from
VBA (excel 2003) to fortran dll (compiled using CVF 6.6b).

debug in cvf environment shows some of the arguments are passed
correctly while some are not.

I attached part of the code here. The arguments passed correctly are
f_max, ppw, ma, para_H2. For other array arguments, only the first
elements are passed correctly.

any comments or suggestions are appreciated.

fortran side

subroutine simple (control, ma, f_max, ppw, &
                acc, profile, degradation, &
               tabk, para_H2, node_depth, layer_depth, &
               out_a)

!DEC$ATTRIBUTES DLLEXPORT:: simple
!DEC$ATTRIBUTES ALIAS: 'simple':: simple

integer(4) :: i, j, k, m,  boundary, nt_out, nlayer, N_spr, lay_max ,
N, lay,          &
           nt, n_o, n_new, n_ma, ndt, N_obs

integer(4) ::  n_sublay(100), node_index(100), layer_index(100), &
                       material (2000)

integer(4) :: control(7), ma(100)

real(8) ::  f_max, ppw, dtt, vs_r, rho_r,  v_in_0, a_in_0, dt, d_t,
duration ,&
          v_in_1, a_in_1, eps, ac1, ac2, xi, t_k(8), a_k(8), b_k(8),
tabk(8,3), sum

real(8) :: t(10000), a(10000), acc(10000,2), a_in(100000), tt(100000),
&
                     h(100), v(100), x(100), r(100), G(100),
profile(100,4),  &
                                     strn_G(20,100), G_vec(20,100), strn_x(20,100), x_vec(20,100),
&
                                     sublay(100), dh(100), node_depth(100), layer_depth(100),  &
                                     dz(2000), vs(2000), rho(2000), damp(2000), Gmax(2000),
strain_G(20,2000), G_vector(20,2000), &
                                     v_est_1(2000), a_nt(2000), d_1(2000), tau_1(2000),
gamma_0(2000), d_gamma_0(2000), &
                                     v_est_2(2000), v_nt(2000), d_2(2000), tau_0(2000),
gamma_1(2000), d_gamma_1(2000), &
                                     out_a(10000,100), out_v(10000,100), out_d(10000,100),
out_gamma(10000,100), out_tau(10000,100),  &
                                     max_a(100), max_v(100), max_d(100), max_gamma(100),
max_tau(100), &
                                     degradation(20,200), ak(500,2000), fy(500,2000),
ss(500,2000),  &
                                     x_ini(100), Qfactor(100), chi(100), w_k(8,100),
x_vec_n(20,100), w_k_sub(8,2000), &
                                     memory_0(8,2000), memory_1(8,2000), a_val(100), b_val(100),
a_val_sub(2000), b_val_sub(2000), &
                                     para_H2(10,50), s_val(100), beta(100), s_val_sub(2000),
beta_sub(2000)

!!!!!! main part of program omitted

end

subroutine make_spring_HY (ak, fy, Gmax, a, b, s, beta, N_spr)
integer(4) ::  j,  N_spr
real(8) :: ak(N_spr), fy (N_spr), G_tan( N_spr), &
       &  tau (N_spr), gamma(N_spr),   Gmax ,  &
           &  strain_G(N_spr), G_vector(N_spr), factor, ratio, a, b, s,  beta

        gamma(1)=10.0**-6.0; factor=10.0**0.05
        do i=2, N_spr;  gamma(i)=gamma(i-1)*factor; enddo

        do j=1,N_spr
        call my_HY (ratio, a, b, s, beta, gamma(j))
        tau(j)=Gmax*ratio*gamma(j)
    enddo

    G_tan(1)=tau(1)/gamma(1)    ! 1st tangent modulus
    do j=2,N_spr
        G_tan(j)=(tau(j)-tau(j-1))/(gamma(j)-gamma(j-1))
    enddo
    do j=1,N_spr-1
        ak(j)=G_tan(j)-G_tan(j+1)
        fy(j)=ak(j)*gamma(j)
    enddo
    ak(N_spr)=G_tan(N_spr) ;  fy(N_spr)=ak(N_spr)*gamma(N_spr)
end

subroutine my_HY (ratio, a, b, s, beta, gamma)
real(4) ratio, a, b, s, beta, gamma, strain_ref
strain_ref=a+gamma*b;  ratio=1/(1+beta*(gamma/strain_ref)**s)
end

subroutine iwan_parallel (stress, si, aki, fyi, N_spr, d_gamma)
integer(4) N_spr
real(8) :: force, si(N_spr), aki(N_spr), fyi(N_spr), d_gamma, stress

force = 0.0
do i=1,N_spr
    si(i) = si(i) + aki(i) * d_gamma
    if (si(i) > fyi(i)) then
        si(i) = fyi(i)
    else if (si(i) < -fyi(i) )        then
        si(i) = -fyi(i)
    endif
    force = force + si(i)
enddo
stress = force
end

VBA part

Private Declare Sub simple Lib "hytest.dll" (ByRef control As Long,
ByRef ma As Long, ByRef f_max As Double, ByRef ppw As Double, _
               ByRef acc As Double, ByRef profile As Double, ByRef
degradation As Double, _
               ByRef tabk As Double, ByRef para_H2 As Double, ByRef
node_depth As Double, ByRef layer_depth As Double, _
               ByRef out_a As Double)
Option Explicit
Option Base 1
Sub wave()

Dim f_max, ppw As Double

Dim i, j, nt_out, nlayer, n_ma As Long

Static control(7), ma(100) As Long

Dim acc(10000, 2), profile(100, 4), _
    degradation(20, 200), tabk(8, 3), para_H2(10, 50) As Double

Dim node_depth(100), layer_depth(100) As Double

Dim out_a(10000, 100)

For i = 1 To 100
node_depth(i) = 0#
layer_depth(i) = 0#

For j = 1 To 10000

out_a(j, i) = 0#

Next j
Next i

f_max = CDbl(Worksheets("control").Cells(1, 1).Value)
ppw = CDbl(Worksheets("control").Cells(1, 2).Value)

control(1) = CLng(Worksheets("control").Cells(1, 3).Value)
control(2) = CLng(Worksheets("control").Cells(1, 4).Value)
control(3) = CLng(Worksheets("control").Cells(1, 5).Value)
control(4) = CLng(Worksheets("control").Cells(1, 6).Value)
control(5) = CLng(Worksheets("control").Cells(1, 7).Value)
control(6) = CLng(Worksheets("control").Cells(1, 8).Value)
control(7) = CLng(Worksheets("control").Cells(1, 9).Value)

nlayer = control(3)
nt_out = control(4)
n_ma = control(5)

For i = 1 To nt_out
acc(i, 1) = CDbl(Worksheets("incident").Cells(i, 1).Value)
acc(i, 2) = CDbl(Worksheets("incident").Cells(i, 2).Value)
Next i

For i = 1 To nlayer + 1
profile(i, 1) = CDbl(Worksheets("profile").Cells(i, 1).Value)
profile(i, 2) = CDbl(Worksheets("profile").Cells(i, 2).Value)
profile(i, 3) = CDbl(Worksheets("profile").Cells(i, 3).Value)
profile(i, 4) = CDbl(Worksheets("profile").Cells(i, 4).Value)
ma(i) = CLng(Worksheets("profile").Cells(i, 5).Value)
Next i

For i = 1 To 20
For j = 1 To 4 * n_ma
degradation(i, j) = CDbl(Worksheets("curve").Cells(i, j).Value)
Next j
Next i

For i = 1 To 8
tabk(i, 1) = CDbl(Worksheets("tabk").Cells(i, 1).Value)
tabk(i, 2) = CDbl(Worksheets("tabk").Cells(i, 2).Value)
tabk(i, 3) = CDbl(Worksheets("tabk").Cells(i, 3).Value)
Next i

For i = 1 To 10
For j = 1 To 50
para_H2(i, j) = CDbl(Worksheets("h2_n").Cells(i, j).Value)
Next j
Next i

Call simple(control(1), ma(1), f_max, ppw, _
                acc(1, 1), profile(1, 1), degradation(1, 1), _
                tabk(1, 1), para_H2(1, 1), node_depth(1),
layer_depth(1), _
             out_a(1, 1))

For i = 1 To nt_out
For j = 1 To nlayer + 1

  Worksheets("out").Cells(i, j).Value = out_a(i, j)
Next j
Next i

End Sub

On 29 mei, 00:01, formulae translator <liwei19742@gmail.com> wrote:

> Dear all,

> I encounter a strange problem when I am trying to pass arguments from
> VBA (excel 2003) to fortran dll (compiled using CVF 6.6b).

> debug in cvf environment shows some of the arguments are passed
> correctly while some are not.

> I attached part of the code here. The arguments passed correctly are
> f_max, ppw, ma, para_H2. For other array arguments, only the first
> elements are passed correctly.

> any comments or suggestions are appreciated.

It looks as if only the scalar variables are passed correctly.
That does seem to make sense to me:

In VB you need to pass arrays like: ByRef array() As Double

In the code you posted the interfaces are missing the ().

Regards,

Arjen

On May 29, 2:50 am, Arjen Markus <arjen.mar@wldelft.nl> wrote:

Dear Arjen,

Thanks a lot for your prompt reply.

I tried the way you suggested, but got a compilor error (type
mismatch) from VBA.

The example in CVF document also has no "()" in "byref array as
double".

except for the two scalars (F_max and ppw), I have two arrays (ma and
para_H2) passed correctly.

I suspect the reason is that total size of arguments exceeds some
limit, but I am not sure because I cannot find any evidence to support
this.

Wei

You can test that hypothesis by stripping your code down to nothing but
variable initialization in VB and the Fortran subroutine call;
eliminate everything except for the subroutine arguments.  If the values
look right when you do that, then the problem is elsewhere.  Add
'implicit none' to the Fortran code -- it can save you some bugs later on.

Louis

On May 29, 1:06 pm, Louis Krupp <lkr@pssw.nospam.com.invalid>
wrote:

Thanks for Louis' reply
I found the reason by playing with VBA part.
I can NOT define more than one array in one line.
It's so strange because I never heard anyone mentioned this.

The adjusted code should be following:

Dim f_max, ppw As Double

Dim i, j, nt_out, nlayer, n_ma As Long

Dim control(7) As Long
Dim ma(100) As Long

Dim acc(10000, 2) As Double
Dim profile(100, 4) As Double
Dim degradation(20, 200) As Double
Dim tabk(8, 3) As Double
Dim para_H2(10, 50) As Double

Dim node_depth(100) As Double
Dim layer_depth(100) As Double

Dim out_a(10000, 100) As Double

formulae translator wrote:
> Thanks for Louis' reply
> I found the reason by playing with VBA part.
> I can NOT define more than one array in one line.
> It's so strange because I never heard anyone mentioned this.

> The adjusted code should be following:

> Dim f_max, ppw As Double

> Dim i, j, nt_out, nlayer, n_ma As Long

> Dim control(7) As Long
> Dim ma(100) As Long

[...]

I don't know very much about VBA, but looking at that syntax, I wonder
if the problem isn't that to define more than one array on the same
line, you'd have to do it like:

Dim control(7) As Long, ma(100) As Long

and that if you only do

Dim control(7), ma(100) As Long

then ma gets defined properly, but control gets typed as whatever VBA's
implicit typing is ("variant", I think).

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

On 30 mei, 06:03, Brooks Moses <bmoses-nos@cits1.stanford.edu>
wrote:

Oh, a type "variant" would be a very bad idea!
It is a "polymorphic" type that only VB can handle properly -
a bit like array descriptors for assumed-shape arrays:
you can not (easily/portably) pass these to, say, C.

Quite likely that that is the problem.

Regards,

Arjen

They can lead to other problems, too....
http://worsethanfailure.com/Articles/My-Friends-Just-Call-Me-Error.aspx

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

On May 29, 4:57 pm, formulae translator <liwei19742@gmail.com>
wrote:
...

> I can NOT define more than one array in one line.
> It's so strange because I never heard anyone mentioned this.

It's not that you cannot define more than one array (any variable
type, actually) on one line but that the syntax

Dim A As Integer, B

results in variable B being a Variant as it was not provided a type
and therefore, defaults to Variant.  This is documented in VB albeit
in older versions a little obtusely but is well discussed in VB-
related newsgroups.

So, from your original posting,

Dim f_max, ppw As Double
Dim i, j, nt_out, nlayer, n_ma As Long
Static control(7), ma(100) As Long
...
Dim out_a(10000, 100)

each of the variables except in the first three lines are Variants
with the exception of the last one on each line which.  In the last
line out_a is also a Variant array.

I'll make a side note for the future that if you had pared your
example down to something approaching the near minimum to demonstrate
the problem on the first post I probably would have taken the time to
look at it enough and spotted the issue.  As it was, there was so much
stuff posted I didn't look at any of it.

On May 30, 7:59 am, dpb <bozart@gmail.com> wrote:
...

> So, from your original posting,

> Dim f_max, ppw As Double
> Dim i, j, nt_out, nlayer, n_ma As Long
> Static control(7), ma(100) As Long
> ...
> Dim out_a(10000, 100)

> each of the variables except in the first three lines are Variants
> with the exception of the last one on each line which.  In the last
> line out_a is also a Variant array.

Boy, I butchered that, didn't I?  Sorry...

Each of the variables in the first three lines are Variants
with the exception of the last one on each line which is the type
specified.  In the last line out_a is also a Variant array as no type
is provided.

Since I'm here anyway, I'll add a couple of other VB-related
comments...

As you chose to do, one of the recommendations often made in coding
style w/ VB is to make one declaration per line so as to avoid the
inadvertent lack of specific type declarations.

As w/ Fortran's Implicit None being an aid in finding type mismatches,
and typos, etc., VB has Option Explicit that serves much the same
purpose.  It is also widely recommended to use that facility
universally.  Unfortunately, by the design of VB it wouldn't have
identified the problem here specifically as the variables in question
were Declare'd but the syntax used made them Variant. :(

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc