Page 2 of 3

Posted: Thu Oct 18, 2007 2:55 pm
by hallodri
use pointer

Code: Select all

*MyString.vstring [...]

Posted: Thu Oct 18, 2007 5:19 pm
by Lazarus404
No, it isn't helping :( Aren't there any examples of using external libs with pointers or structs being passed in and out of PB? I would have though it a necessity to get half of the libraries that exist in PB to work :-S

Thanks,

Posted: Thu Oct 18, 2007 6:18 pm
by tinman
Have you tried something like:

Code: Select all

strng$ = "some string"
*mystruct.type = getString(@strng$)
result$ = PeekS(returnString(*mystruct))
Unfortunately I can't test that here. I can't get the .lib file I've created imported correcrtly. Perhaps you could share the header and c source for your lib if you have it? Or the releavant sections anyway.

The above code can be improved using prototypes, but you can't catch an imported function return as a string according to the docs, so PeekS() is the easiest way to get it as a string.

Posted: Thu Oct 18, 2007 7:50 pm
by Lazarus404
Thanks, but I now get:

POLINK: warning: Unrecognised option 'manifestdependency:"type='win32"; ignored.
POLINK: fatal error: File not found: 'name='Microsoft.VC().Debug.CRT".

I'd guess it's found an error in my dll, so I'll look into this :)

Regards,

Posted: Thu Oct 18, 2007 8:03 pm
by tinman
Sounds like you've got two things going on there:

1) You're using a debug version of your C lib, which probably isn't a problem in itself.
2) You're using some visual C runtime functions. You'll need to link the final executable with the correct library - you can probably get this from the linker command line options in your C lib project's property page. I think you can set extra linker options for the PB compiler in the IDE somewhere.

Out of curiosity, how did you get your (I assume) VC library to import correctly, I can't get it to work at all here :(

Posted: Thu Oct 18, 2007 8:05 pm
by Lazarus404
I specified the complete path to the lib. Here's what I actually have (not that mine is working either :( )

ImportC "C:\Documents and Settings\Lee\My Documents\__Development\devlib\devlib.lib"

n_alloc_string( str$ )
n_val_string( str )

EndImport

Posted: Thu Oct 18, 2007 9:28 pm
by tinman
Looks like the PellesC linker (polink.exe) does not like the "/manifestdependency" linker option that MSVC adds to the resulting .lib file. I installed PellesC to get the latest link (NB: this might have an effect on it finding the runtime libraries if you have probs with that) but that still didn't work.

What did work was editing out the section of the .lib file which read as follows (replace it all with spaces):

Code: Select all

/manifestdependency:"type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'"

Posted: Thu Oct 18, 2007 11:27 pm
by Lazarus404
That didn't work for me. Windows throws up a debug error, asking if I'd like to open it in Visual Studio. Not good.

Posted: Fri Oct 19, 2007 8:41 am
by tinman
But that at least sounds like it's linked and you're getting an exception/assert/whatever in your code as it runs. What type of debug error are you getting?

Posted: Fri Oct 19, 2007 10:01 am
by Lazarus404
I'm not sure. It's one of those Windows debug errors that allow you to traverse the hex values in memory. It's not one I can work out with a "normal" developers eye ;) My guess is, the lib is no longer an acceptable win32 library.

Surely someone has traversed this path before. Aren't there any simple Lib examples for PB?

Posted: Fri Oct 19, 2007 11:01 am
by tinman
I wrote a simple example during the course of this thread, but it really was simple (I can send you the code later, but I forgot my memory stick so I don't have it with me). The code was something like this:

C lib

Code: Select all

struct lib_struct
{
    int type;
    char* f;
};

extern "C" struct lib_struct* getString(char* string)
{
    static struct lib_struct foo;
    foo.f = string;
    foo.type = strlen(string);
    return(&foo);
}

extern "C" char* returnString(struct lib_struct* str)
{
    return(str->f);
}
Compile it as a static library, release mode, making sure it's compiled as __cdecl.
I found that I had to turn off link time optimisation options for the lib to import correctly in PB.

Then I had to edit the library in the hex editor as I described.

PB code

Code: Select all

ImportC "mylib.lib"
    getString.l(string.s)
    returnString.l(struct.l)
EndImport

Structure lib_struct
    type.l
    f.l
EndStructure

*mystruct.lib_struct = getString("foo")
result$ = PeekS(returnString(*mystruct))
Debug result$
And that worked when I ran it. No debug errors. I never checked the value of *mystruct\type though. And of course that code is very simple, there's no calls to any memory allocation/free functionsm, etc.

Also, I downloaded the PellesC compiler. Perharps your problem is that during link the polink.exe cannot find the relevant MSVC runtime .lib file. You should have them somewhere already if you have MSVC but I struggled to figure out how to pass options to the linker. Every time I tried I got an error complaining about my linker options command file.

The other thing to worry about is I don't know how the system determines the version of the MSVC runtime DLL to load. That manifestdependancy linker option looks like it would add something to your application's manifest saying what version of the MSVC runtime it should try to load, as it would get loaded from the side by side DLL cache. If you are trying to link against one version but remove the manifestdependancy line and have a later version of the DLL on the system, what happens then? Is there any more information about what version to use or does it go for the one installed in c:\windows\system32 (i.e. not the versioned side by side DLLs) - which could point to anything.

Posted: Fri Oct 19, 2007 11:25 am
by Lazarus404
Thanks for that tinman. I'll have a go and let you know how I get on.

Posted: Sat Oct 20, 2007 4:29 pm
by Lazarus404
Hi guys, tinman,

I've reached another halt in my attempts to create a DLL using a C lib in PB. I've sorted the whole "using a C lib" issue, but I can't find a way around passing structures into or out of ProcedureCDLL's.

Here's what I want...

Code: Select all

ImportC "mylib.lib"
    getString.l(string.s)
    returnString.l(struct.l)
EndImport

Structure lib_struct
    type.l
    f.l
EndStructure

ProcedureCDLL.lib_struct parseString( *foo.lib_struct )
str$ = returnString(*foo)
ProcedureReturn getString(str$)
EndProcedure
Or something to this effect. Obviously, normally, some sort of processing would go on, here. However, any values returned from the DLL need to be understood by the calling application, which is why the returned values need to be structs. I can cope with being able to pass pointers only, as I can always pass the values back into a generic C dll for conversion, but I don't know how to do this, either.

Any help would be great.

Regards,

Posted: Sat Oct 20, 2007 10:19 pm
by tinman
You've got two choices. Either return a pointer to a structure, or have the application pass the address of a structure into your procedure and fill it in.

Code: Select all

Structure mystruct
    a.l
    b.l
EndStructure

ProcedureCDLL.l blah(*str.mystruct)
    ProcedureReturn *str
EndProcedure

Define.mystruct a_struct
a_struct\a = 23
a_struct\b = 69

*aaa.mystruct = blah(@a_struct)
Debug Str(*aaa\a)
Debug Str(*aaa\b)
You have to make it a .l for the return type. You can't specify a pointer type as a return.
be structs. I can cope with being able to pass pointers only, as I can always pass the values back into a generic C dll for conversion, but I don't know how to do this, either.
See above - you return a .l but just use it as a pointer to the type in question. If you're calling this DLL from e.g. C then you just define the return type in the header file as a pointer to the type you need e.g.:

Code: Select all

struct mystruct
{
    long a;
    long b;
};

/* Or some variant of this, I can never remeber the ordering of declspecs */
__declspec(dllimport) struct mystruct* __cdecl blah(struct mystruct* str);

Posted: Mon Oct 22, 2007 1:14 am
by Lazarus404
Tsk* I can't do it. The language I wish to consume the dll, although capable of handling pointers, can only do so by wrapping the pointer in a struct before handling it. This means I can't wrap it in PB, because PB doesn't like to handle the structs themselves but will the pointer. It's like the chicken and egg issue. :(

As for the example you gave, tinman. Thanks, but unless I can have this

Code: Select all

ProcedureCDLL.l blah(str.mystruct)
    ProcedureReturn str
EndProcedure 
instead of this

Code: Select all

ProcedureCDLL.l blah(*str.mystruct)
    ProcedureReturn *str
EndProcedure 
then it's all for nothing :cry:

Oh well