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

Calling a dll c function returning a pointer


Hi,

Everything was O.K. When I wrote:

subroutine fun1(input1)
      interface
         real*4 function fun2(input2)
!dec$ attributes  c,dllimport,alias:'_fun2' :: fun2
            real*4 input2
         end function fun2
      end interface

      real*4 a,b
      a = 0
      if(input1.eq.0) then
         b = fun2(a)
      end if

      return
end

But, when I changed the C function so it's returning a pointer to
float instead of a float:

subroutine fun1(input1)
      interface
         function fun2(input2)
!dec$ attributes  c,dllimport,alias:'_fun2' :: fun2
            real*4, pointer::fun2(:)
            real*4 input2
         end function fun2
      end interface

      real*4 a,b
      real*4, pointer::fun2_output(:)

      a = 0

      if(input1.eq.0) then
         fun2_output => fun2(a)
         b = fun2_output(0)
      end if

      return
end

I got:

test.obj : error LNK2001: unresolved external symbol _fun2
Debug/project.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

project.dll - 2 error(s), 0 warning(s)

Please help me! I've searched the entire internet for an answer...

??????? ???? ?????? wrote:

| Hi,
|
(snip)
| But, when I changed the C function so it's returning a pointer to
| float instead of a float:
|
| subroutine fun1(input1)
|      interface
|         function fun2(input2)
| !dec$ attributes  c,dllimport,alias:'_fun2' :: fun2
|            real*4, pointer::fun2(:)
|            real*4 input2
|         end function fun2
|      end interface
|
|      real*4 a,b
|      real*4, pointer::fun2_output(:)
|
|      a = 0
|
|      if(input1.eq.0) then
|         fun2_output => fun2(a)
|         b = fun2_output(0)
|      end if
|
|      return
| end
|
| I got:
|
| test.obj : error LNK2001: unresolved external symbol _fun2
| Debug/project.dll : fatal error LNK1120: 1 unresolved externals
| Error executing link.exe.

For the start, you haven't shown us the C code.

There are two separate issues, though: linking problem (which would
be simple to solve) and the incompatibility problem (which requires
a bit more).

As for the linking problem: you're apparently using CVF or IVF.
I can't tell what exactly happened, but here are some tips:

1) Ensure that the C function is
   a) marked with extern "C" in the code
   b) exported from the dll (via __declspec(dllexport) or .def file)
2) Check its exact alias using "Dependency walker" tool (it's in
   CVF or VS program groupm, or in http://www.dependencywalker.com)
   or, from command line:
   dumpbin /exports yourdll.dll
3) Of course, ensure that you link the Fortran project with dll's
   export library (yourdll.lib)

However, there's another problem: namely, the C and Fortran prototypes

float* fun2(float);  and

real*4, pointer::fun2(:)

do NOT match. Fortran pointer to an array is much more complex stuff
that mere float*. This will crash or misbehave in run-time even when
you manage to get the linking right.

There are numerous ways to redesign it, but I'm reluctant to delve
into details until you tell us what the C function does and who
is supposed to allocate the memory for the pointer. The cleanest
path would probably be along these lines:

extern "C" void __declspec(dllexport) fun2(float f, float* r);
....
interface
  subroutine fun2(f, r)
  !DEC$ATTRIBUTES C, ALIAS: "_fun2":: fun2
  real, intent(in):: f
  real, intent(out):: r(*)
  end subroutine
end function

--
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Yes, that would help a lot.

> There are two separate issues, though: linking problem (which would
> be simple to solve) and the incompatibility problem (which requires
> a bit more).
> As for the linking problem: you're apparently using CVF or IVF.
> I can't tell what exactly happened, but here are some tips:
> 1) Ensure that the C function is
>    a) marked with extern "C" in the code

extern "C" is used when compiling C code with a C++ compiler,
usually when mixed with C++ code.  Otherwise, is the C function
named _fun2, as the message indicates?

>    b) exported from the dll (via __declspec(dllexport) or .def file)
> 2) Check its exact alias using "Dependency walker" tool (it's in
>    CVF or VS program groupm, or in http://www.dependencywalker.com)
>    or, from command line:
>    dumpbin /exports yourdll.dll
> 3) Of course, ensure that you link the Fortran project with dll's
>    export library (yourdll.lib)
> However, there's another problem: namely, the C and Fortran prototypes
> float* fun2(float);  and
> real*4, pointer::fun2(:)
> do NOT match. Fortran pointer to an array is much more complex stuff
> that mere float*. This will crash or misbehave in run-time even when
> you manage to get the linking right.

Note that functions returning pointers are a little complicated,
even in C code.  The usually choices are returning a pointer to
static data, returning a pointer to one of the arguments (or some part
of an argument), or allocating memory and returning a pointer to it.
The last requires the caller to free the memory, often inconvenient.

> There are numerous ways to redesign it, but I'm reluctant to delve
> into details until you tell us what the C function does and who
> is supposed to allocate the memory for the pointer. The cleanest
> path would probably be along these lines:

-- glen
glen herrmannsfeldt wrote:
| Jugoslav Dujic wrote:

|
|| (snip)
||| But, when I changed the C function so it's returning a pointer to
||| float instead of a float:
|||
||| subroutine fun1(input1)
|||      interface
|||         function fun2(input2)
||| !dec$ attributes  c,dllimport,alias:'_fun2' :: fun2
|||            real*4, pointer::fun2(:)
|||            real*4 input2
|||         end function fun2
|||      end interface
|
|||      real*4 a,b
|||      real*4, pointer::fun2_output(:)
|
|||      a = 0
|
|||      if(input1.eq.0) then
|||         fun2_output => fun2(a)
|||         b = fun2_output(0)
|||      end if
|
|||      return
||| end
|
||| I got:
|
||| test.obj : error LNK2001: unresolved external symbol _fun2
||| Debug/project.dll : fatal error LNK1120: 1 unresolved externals
||| Error executing link.exe.
|
|| For the start, you haven't shown us the C code.
|
| Yes, that would help a lot.
|
|| There are two separate issues, though: linking problem (which would
|| be simple to solve) and the incompatibility problem (which requires
|| a bit more).
|
|| As for the linking problem: you're apparently using CVF or IVF.
|| I can't tell what exactly happened, but here are some tips:
|
|| 1) Ensure that the C function is
||    a) marked with extern "C" in the code
|
| extern "C" is used when compiling C code with a C++ compiler,
| usually when mixed with C++ code.  Otherwise, is the C function
| named _fun2, as the message indicates?
<snip>

I took for granted that the C compiler in question is MS VC++
(the most popular choice in conjunction with CVF); for files
with .cpp extension, it assumes C++ name decoration (and I'm not
sure about files with .c extension). Without C++ name decoration,
its linkage alias (decoration) consists of only underscore-prefix
(assuming __cdecl calling convention), case-sensitive of course.
Thus, "extern "C" float* fun(...)" will get decorated as "_fun"
in the .obj file.

But yes, a lot of my reply was based on (educated) guesswork.
Seeing the C code would definitively help.

--
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

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