Extern doesn't work?
BlitzMax Forums/BlitzMax Programming/Extern doesn't work?
| ||
Keep's telling it's an undefined reference, even though it's clearly not. The code belows imports a C++ file. it compiles fine, but whenever I call a function contained within it, that's when it fails at the linking stage. C:/Program Files/BlitzMax/ARPG/.bmx/AI.bmx.gui.debug.win32.o(code+0x185): undefined reference to `CreateLine' C:/Program Files/BlitzMax/ARPG/.bmx/AI.bmx.gui.debug.win32.o(code+0x1ac): undefined reference to `CreateLine' Referencing the two times I called the function in the test code below.. BlitzMax Code. Import "Line2D.cpp" Public Extern "win32" Function CreateLine:Int( x1#,y1#,x2#,y2# )="CreateLine" Function SetLine( line,x1#,y1#,x2#,y2# ) Function LineCast:Int( line1,line2,result ) Function ResultX:Int(result) Function ResultY:Int(result) Function CreateResult:Int() End Extern Graphics 640,480,0 Local x1#,y1#,x2#,y2# x1=20 y1=20 Local lin1,lin2 lin1 = createLine( x1,y1,x2,y2 ) lin2 = createLine( 320,0,325,480 ) If lin1=0 RuntimeError "Line was not created." Repeat Cls x2=MouseX() y2=MouseY() DrawLine x1,y1,x2,y2 DrawLine 320,0,325,480 Flip Until KeyDown(1) C++ Code, call it "Lines2d.cpp" class XPOINT { public: float x, y; }; class XLINE { public: XPOINT o, p; float m; float c; }; float min( float v1,float v2 ) { if(v1<v2) return v2; return v1; } float max( float v1,float v2) { if(v1>v2) return v1; return v2; } XLINE CreateLine( float x1,float y1,float x2,float y2){ XLINE out; out.o.x=x1; out.o.y=y1; out.p.x=x2; out.p.y=y2; return out; } void SetLine( XLINE &l,float x1,float y1,float x2,float y2){ l.o.x=x1; l.o.y=y1; l.p.x=x2; l.p.y=y2; } XPOINT * CreateResult(){ return( new XPOINT); } float ResultX( XPOINT *i){ return i->x; } float ResultY( XPOINT *i){ return i->y; } int LineCast( XLINE &a, XLINE &b, XPOINT *i ) { // null width lines cannot intercept if ( (a.p.x == a.o.x) || (b.p.x == b.o.x) ) { return false; } // calculate gradients a.m = (a.p.y - a.o.y) / (a.p.x - a.o.x); b.m = (b.p.y - b.o.y) / (b.p.x - b.o.x); // parallel lines can't intercept if (a.m == b.m) { return false; } // calculate axis intersect values a.c = a.o.y - (a.m * a.o.x); b.c = b.o.y - (b.m * b.o.x); // calculate x point of intercept i->x = (b.c - a.c) / (a.m - b.m); // is intersection point in segment if ( i->x < min(a.o.x, a.p.x) || i->x > max(a.o.x, a.p.x) ) { return false; } if ( i->x < min(b.o.x, b.p.x) || i->x > max(b.o.x, b.p.x) ) { return false; } // calculate y point of intercept i->y = (a.m * i->x) + a.c; // points intercept return true; }; |
| ||
exchange Extern "win32" with extern (without "win32") extern "win32" is a predefined extern link to win32 libraries. |
| ||
That was the first thing I tried, same deal. Just remember having to use a certain "blah" extern directive when this happened before. Know of the others? I havn't even bothered looking in the docs. Last place they'll be. |
| ||
Hi Antony, I think C++ name-mangling may be a problem, your cpp file may not be exporting a function called "CreateLine" as a result. try this: extern "C" XLINE CreateLine( float x1,float y1,float x2,float y2){ XLINE out; out.o.x=x1; out.o.y=y1; out.p.x=x2; out.p.y=y2; return out; } |
| ||
btw: even if you get that to work, you can't work with C++ objects in BM |
| ||
Hi Dremora, That isn't true. If you read the 'Advanced Topics' section of the language help, you'll see that you can work with C++ classes in BlitzMAX. |
| ||
Then you should have seen the restrictions of that, that you can't work with it in BM as you are used by normal types. |
| ||
Either as Robert said...extern "C" XLINE CreateLine( float x1,float y1,float x2,float y2) or Function CreateLine:Int( x1#,y1#,x2#,y2# )="_Z10CreateLineffff" 10 is the length of the function name and ffff stands for 4 floats |
| ||
Robert's suggestion worked. Thanks. But, turns out the code wasn't worth importing anyway. It has to be most inaccurate line intersection routine ever devised by crack addled man. Anyone got a good one? Or you know, one that just actually works? (Frustration rising.) |
| ||
Don't matter, found swift's one in the code archives. WHY DIDN'T I CHECK THERE FIRST!. [morphs into the incredible hulk] |
| ||
Great, swift's func doesn't work either.Function Lines_Intersect(Ax#, Ay#, Bx#, By#, Cx#, Cy#, Dx#, Dy#) Local Rn# = (Ay#-Cy#)*(Dx#-Cx#) - (Ax#-Cx#)*(Dy#-Cy#) Local Rd# = (Bx#-Ax#)*(Dy#-Cy#) - (By#-Ay#)*(Dx#-Cx#) Print RD+":"+rn If Rd# = 0 Return False Else Local Sn# = (Ay#-Cy#)*(Bx#-Ax#) - (Ax#-Cx#)*(By#-Ay#) Intersection_AB# = Rn# / Rd# Intersection_CD# = Sn# / Rd# Intersection_X# = Ax# + Intersection_AB#*(Bx#-Ax#) Intersection_Y# = Ay# + Intersection_AB#*(By#-Ay#) Return True EndIf End Function always returns true, yet the itnersection point is always accurate, but it's as if the second line is infinitely long. |
| ||
You're correct that SSwift's code checks if the first line crosses an infinitely long line on the angle defined by the two points. Here's a slightly modified and commented version of SSwift's code which only returns true if the lines intersect within the length of the second line. Function Lines_Intersect(Ax#,Ay#,Bx#,By#,Cx#,Cy#,Dx#,Dy#) Rn#=(Ay#-Cy#)*(Dx#-Cx#)-(Ax#-Cx#)*(Dy#-Cy#) Rd#=(Bx#-Ax#)*(Dy#-Cy#)-(By#-Ay#)*(Dx#-Cx#) If Rd# = 0 ; Lines are parallel. ; If Rn# is also 0 then lines are coincident. All points intersect. ; Otherwise, there is no intersection point. Return False Else ; The lines intersect at some point. Calculate the intersection point. Sn# = (Ay#-Cy#)*(Bx#-Ax#) - (Ax#-Cx#)*(By#-Ay#) Intersection_AB# = Rn# / Rd# Intersection_CD# = Sn# / Rd# ; MAKE SURE IT FITS WITHIN THE FIRST LINE If Intersection_AB#<0.0 Or Intersection_AB#>1.0 ; THEY INTERSECT, BUT BEYOND THE LENGTH OF LINE 2. Return False Else ; MAKE SURE IT FITS WITHIN THE SECOND LINE If Intersection_CD#<0.0 Or Intersection_CD#>1.0 Return False Else Intersection_X# = Ax# + Intersection_AB#*(Bx#-Ax#) Intersection_Z# = Ay# + Intersection_AB#*(By#-Ay#) Return True End If End If EndIf End Function |
| ||
Graphics 640,480,0 Local a:Vector2=New Vector2 Local b:Vector2=New Vector2 Local c:Vector2=New Vector2 Local d:Vector2=New Vector2 Local i:Vector2=New Vector2 a.x=34 a.y=62 b.x=42 b.y=87 c.x=50 c.y=0 d.x=43 d.y=100 While Not KeyHit(KEY_ESCAPE) 'Draw a circle DrawLine a.x,a.y,b.x,b.y DrawLine c.x,c.y,d.x,d.y If (linesIntersect2D(a,b,c,d,Null)) DrawText "Lines Intersect",300,300 Else DrawText "No Intersection",300,300 End If Flip Cls FlushMem End While Type Vector2 Field x:Float Field y:Float End Type Type Vector3 Extends Vector2 Field z:Float End Type 'Tests for the intersection of two lines in 2 dimensions. Each line is defined by a start and an end point. 'Returns True if the lines intersect or false otherwise. If they do intersect, outIntersect 'is set to the coordinates of the intersection. outIntersect can be Null. Function linesIntersect2D(p1:Vector2,p2:Vector2,p3:Vector2,p4:Vector2, outIntersect:Vector2) 'Eqn of two lines: ' lineA = p1 + uA(p2-p1) ' lineB = p3 + uB(p4-p3) 'Put lineA = lineB, and solve for uA, gives us: uA:Float= ((p4.x-p3.x)*(p1.y-p3.y)) - ((p4.y-p3.y)*(p1.x-p3.x)) temp:Float= ((p4.y-p3.y)*(p2.x-p1.x)) - ((p4.x-p3.x)*(p2.y-p1.y)) uB:Float = ((p2.x-p1.x)*(p1.y-p3.y)) - ((p2.y-p1.y)*(p1.x-p3.x)) 'Check if lines are parallel If (temp=0) Return False End If uA :/ temp uB :/ temp intersectX:Float = p1.x+uA*(p2.x-p1.x) intersectY:Float = p1.y+uA*(p2.y-p1.y) If ((uA >= 0) And (uA <= 1) And (uB >= 0) And (uB <= 1)) If (outIntersect) outIntersect.x=intersectX outIntersect.y=intersectY End If Return True Else Return False End If End Function |
| ||
Your turn Syb? :) Thanks both, I'll use them both equally..or something. :) |